Skip to content

Conversation

timacdonald
Copy link
Member

@timacdonald timacdonald commented Aug 18, 2025

Imagine you have an application that uses symlinks to do zero-downtime deployments.

The application runs php artisan nightwatch:agent via a daemon.

The application has just performed a deployment where its own dependencies have changed.

When the agent shuts down, the PHP execution flow returns to the parent Laravel application. The Laravel application will then require classes that have not yet been required. If any of those files are missing after the update, because of the dependency update, it is possible that the command errors out because of requiring missing files.

Instead, we now always exit the current PHP process within the agent itself, so control never returns to the Laravel application.

This is a bit of a tradeoff because it means that the terminating callbacks or other event listeners will not be triggered.

Another alternative is to do what we have done in the agent and eagerly load all the application's dependency files, but that feels extremely heavy handed and could cause unexpected side-effects, e.g., memory usage increases, actual PHP side-effects because of executing code while requiring files. It also may still have issues if terminating callbacks, somewhere in the code stack, manually require files that are now missing.

This is also heavy handed...but feels like the right direction to me.

Laravel is used as a shell to boot the agent command but is not used for shutdown any longer.

@@ -58,6 +58,7 @@
$ingestTimeout ??= 10;
/** @var ?string $server */
$server ??= (string) gethostname();
$testing = (bool) ($_SERVER['NIGHTWATCH_TESTING'] ?? false);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to be able to avoid exit while we are running the testsuite.

Comment on lines +88 to +92
if ($testing) {
return;
} else {
exit(1);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, this would just return, but I think we should exit with an error code if we cannot read the signature file.

@timacdonald
Copy link
Member Author

Gonna sit on this one and see if we have continued reports of the issue.

@timacdonald timacdonald marked this pull request as draft August 20, 2025 04:59
@Propaganistas
Copy link

Propaganistas commented Aug 26, 2025

Perhaps slight off-topic, but highly related:

This PR tackles the shutdown of the agent in symlink deployment environments. But I'd like to know more about how the agent should be forced to restart/shutdown in such scenario. Saving/fetching/killing the PID feels quite verbose, especially knowing that for queue workers (queue:restart) or Horizon (horizon:terminate) clean ways exist.

Or maybe restarts or shutdowns aren't necessary after all and the agent is agnostic of the application it was launched from?

It might be a good addition anyway to add some pointers about this to the docs to avoid confusion? https://nightwatch.laravel.com/docs/getting-started/start-guide#running-the-agent ?

@timacdonald
Copy link
Member Author

@Propaganistas, you should not be manually restarting the agent during a deployment.

The agent automatically restarts when required on a delay.

It does not need to restart the same way that the queue worker or horizon need to restart, as it is a self-contained binary that is not concerned with changing PHP code in your application's code or dependencies.

@timacdonald
Copy link
Member Author

Closing this as we have another approach that results in the shutdown still occurring when an error is not encountered.

@timacdonald timacdonald deleted the fix-loading-missing-files-post-deployment branch September 1, 2025 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants