Skip to content

fix: handle queue work results and isolate chained job dispatching - #106

Open
gr8man wants to merge 3 commits into
codeigniter4:developfrom
gr8man:fix/queue-work-results-and-chain-isolation
Open

gr8man wants to merge 3 commits into
codeigniter4:developfrom
gr8man:fix/queue-work-results-and-chain-isolation

Conversation

@gr8man

@gr8man gr8man commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Description

The queue:work command discarded the outcome of several queue operations, which made failures invisible and could lead to duplicated work.

  • done() — when marking a job as done failed, the worker still printed "The processing of this job was successful" and immediately dispatched the remaining chained jobs. The same job could then be picked up again by another worker while its successors were already queued.
  • later() / failed() — the return values were ignored, so a job that could not be rescheduled or marked as failed left no trace in the logs and stayed RESERVED forever.
  • Chained push() — a failed push still printed that the chained job "has been placed in the queue", hiding lost chains.
  • Chained dispatch exceptions — an exception thrown while dispatching the next job in the chain was caught by the worker's main catch, which turned an already completed job into a failure and rescheduled it, potentially duplicating the whole chain.

Changes

  • src/Commands/QueueWork.php
    • Track whether done() succeeded; on failure, log an error and skip dispatching the chained jobs, so a job whose completion is not persisted is not propagated downstream.
    • Check the result of later() and failed() and log an error when the handler reports a failure.
    • Check the QueuePushResult returned when pushing the chained job: log the handler error and print a red warning instead of the success line.
    • Wrap processNextJobInChain() in try/catch (Throwable $err) and log the exception, so a chain problem can never mark the already completed job as failed or trigger its retry.
    • Use $retryAfter ??= $job->getRetryAfter() in the retry branch so the resolved value is used consistently.

Testing

Added three cases to tests/Commands/QueueWorkTest.php:

  • testRunWithChainedJobWhenDoneFailsDoesNotDispatchNextJob() — done() failure is logged, and the chained job is not pushed.
  • testRunWithChainedJobWhenDispatchThrowsExceptionDoesNotFailOrRetryCurrentJob() — an exception from the chained dispatch does not call failed()/later() for the already processed job.
  • testRunWithChainedJobWhenPushReturnsFailureShowsWarning() — a failed chained push produces the warning message and no success message.

Verified locally on PHP 8.5 with PHPUnit 11.5:

phpunit ....... OK (233 tests, 663 assertions, 27 skipped)
phpstan ....... [OK] No errors
psalm ......... No errors found
php-cs-fixer .. 0 of 75 files would be fixed

This branch has not been deployed

No deployments
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