Skip to content

(feat) Worker: run every job in its own defer() scope - #32

Merged
techmahedy merged 2 commits into
doppar:4.xfrom
techmahedy:techmahedy-4.x
Oct 13, 2026
Merged

techmahedy merged 2 commits into
doppar:4.xfrom
techmahedy:techmahedy-4.x

Conversation

@techmahedy

Copy link
Copy Markdown
Member

Problem

With defer() available in the framework, jobs have no execution scope of their own. A queue worker is a long-lived process, so a callback registered by one job must not survive into the next, and cleanup has to run before the worker records the job's outcome.

Solution

QueueWorker::executeJob() runs $job->handle() through app()->runInDeferScope():

public function handle(): void
{
    $lock = cache()->locked('invoice:' . $this->invoiceId, seconds: 60);

    if (! $lock->get()) {
        throw new \RuntimeException('Invoice is already being sent; the job will be retried.');
    }

    app()->defer(static fn () => $lock->release());

    $this->sendInvoice();
}

Behavior

  • Each job gets its own scope. Callbacks registered by one job never reach the next.
  • Callbacks run when the job finishes, after success or after an exception, before the worker deletes, releases, or fails the job.
  • Works for jobs run in-process and in the timeout child process, because executeJob() is the shared point and the callbacks run in the process that ran the job.
  • Jobs run through dispatchSync() / queueAsSync() / Drain execute inside the caller's execution, so their defer() callbacks belong to the caller's scope. This is unchanged.

Compatibility

The call is guarded with method_exists($app, 'runInDeferScope'), so the
worker behaves exactly as before on framework versions that do not have
defer(). No new requirement is added to composer.json.

Tests

Two tests in QueueWorkerTest, using a container that implements the scope
API:

  • each job runs in its own scope and cleanup runs between jobs (run-a, cleanup-a, run-b, cleanup-b)
  • cleanup runs when a job fails, before the failure is handled

@techmahedy
techmahedy merged commit 74d784a into doppar:4.x Oct 13, 2026
4 checks passed
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.

1 participant