Challenge 3: Diagnose Stale Queue Worker Code — Possible Solution ==================================================================== THE SCENARIO ------------ A deploy updates App\Jobs\ProcessOrder::handle() with new logic (say, fixing a bug in how the order total is calculated). After the deploy, jobs dispatched and processed continue running the OLD, buggy logic — even though the new code is clearly present on disk. WHY THIS HAPPENS ---------------- A `php artisan queue:work` process is a LONG-RUNNING PHP process — when it starts, PHP loads and compiles the application's classes (including ProcessOrder and every other Job class) into memory ONCE, at startup. From that point on, the running worker process keeps using that in-memory version of the code for every job it processes, for as long as the process itself keeps running. Deploying new code to disk (git pull, composer install, etc.) changes the FILES on disk, but does absolutely nothing to the ALREADY-RUNNING queue:work process's in-memory state — that process has no mechanism to notice the files changed underneath it and reload them automatically. It will keep running the exact PHP bytecode it loaded at its own startup time, indefinitely, until the process itself is stopped and restarted. This is fundamentally different from a typical web request handled via PHP-FPM: each web request boots a fresh PHP process (or reuses one from a pool that's very short-lived), so a web request made even one second after a deploy picks up the new code immediately. A queue worker has no such natural "fresh start" moment built into its normal operation — it's designed to keep running for hours or days at a time. THE FIX ------- Run: php artisan queue:restart This command doesn't literally restart the worker process itself — instead, it sets a timestamp in the cache that every running worker checks after finishing its CURRENT job. Once a worker notices the restart signal, it exits gracefully after that job completes. The process supervisor watching over the worker (Supervisor or systemd, per this chapter's earlier section) then automatically starts a brand new worker process — and THAT new process loads the current, up-to-date code from disk at its own startup, picking up the fix. WHY THIS WORKS -------------- - queue:restart is specifically designed to be a SAFE way to cycle workers — it waits for the current job to finish rather than killing the process mid-job, which would risk leaving a job in an inconsistent, partially-completed state. - This gotcha has no direct Django-course parallel specifically because Django doesn't have an equivalent to a long-running, in-memory queue worker process tied to a single deploy step in the same way — this is a genuinely PHP/Laravel-shaped risk that comes from combining PHP's traditionally short-lived request model with Laravel's own long-running worker processes for queues specifically. - The practical takeaway (and why Challenge 2's deployment script includes this step) is that EVERY deploy that could plausibly touch Job class code should include queue:restart as a standard step — not just deploys that are known in advance to change a Job.