Skip to content

Fix captureOutput stale cache, ExecuteTask path tokenization; add ops doc#496

Merged
dereuromark merged 1 commit into
masterfrom
queue-bug-batch
May 13, 2026
Merged

Fix captureOutput stale cache, ExecuteTask path tokenization; add ops doc#496
dereuromark merged 1 commit into
masterfrom
queue-bug-batch

Conversation

@dereuromark
Copy link
Copy Markdown
Owner

Summary

Two correctness bugs from a recent audit plus the ops-first documentation strategic item.

  • Processor::captureOutput() cached the schema check for the lifetime of the worker. A long-running worker started before bin/cake migrations migrate added the output column to queued_jobs would see the cached false for the rest of its runtime and silently drop captured stdout until restart. The auto-detect path now re-checks the schema per call; explicit config (Configure::write('Queue.captureOutput', ...)) is still memoised because that branch never changes mid-process. The per-call cost is a single lookup against an already-cached schema description.
  • ExecuteTask::add() mangled quoted command paths with embedded spaces. explode(' ', $data, 2) split "/usr/local/bin/My Tool" arg1 across command and params[0] — the path arrived at run() broken in half. Switched to str_getcsv with space delimiter + double-quote enclosure so quoted paths survive intact. The plain cmd arg1 arg2 shape continues to work unchanged.

The audit's other "bug 3" concern (the escape => false debug-mode bypass) is already gated correctly by PR #485 — in non-debug mode the check at line 89 throws if escaping is disabled, and the allow-list check at line 94 rejects any non-listed command. Per the project's security-scoping convention, debug-gated paths aren't framed as bugs.

Strategic: ops-first documentation

New docs/guide/operations.md covers what the original audit flagged as missing operational guidance:

  • Sizing workers by CPU vs I/O profile.
  • Supervisor / systemd unit shape that survives crashes, with the Restart=always + bounded workerLifetime recipe.
  • Monitoring signals worth alerting on (stale workers, backlog growth, per-task failure rate) with the actual SQL queries.
  • Failure handling: admin dashboard, bin/cake queue retry <job-id>, the workaround dead-letter pattern until a formal DLQ ships.
  • Schema migrations on live workers: the captureOutput re-check above lets you add columns without restarting workers; anything more invasive needs a rolling restart.
  • Multi-server deployments: the queue_processes heartbeat coordination story and the FileLock caveat for cakephp-queue-scheduler.
  • Common pitfalls for task authors (swallowed exceptions, long blocking sleeps, CLI DSN drift).

Linked from /guide/ index and the sidebar.

Tests

phpunit (186/186 + 7 pre-existing skipped), phpstan, and phpcs all clean.

Three new tests:

  • ProcessorTest::testCaptureOutputReChecksSchemaWhenNotExplicitlyConfigured — memoised explicit-config branch + per-call auto-detect branch.
  • ExecuteTaskTest::testAddPreservesQuotedCommandPathWithSpaces — quoted path round-trip.
  • ExecuteTaskTest::testAddTokenizesPlainSpaceSeparatedArgs — backward compat for the simple case.

… doc

Two correctness bugs from the source-grounded review plus the ops-first
documentation strategic item.

1. Processor::captureOutput() cached the auto-detected schema result for
   the lifetime of the worker. A long-running worker started before
   `bin/cake migrations migrate` added the `output` column to the
   queued_jobs table would then see the cached `false` for the rest of
   its runtime and silently drop captured stdout until restart. The
   auto-detect path now re-checks the schema per call; explicit config
   (Configure::write('Queue.captureOutput', ...)) is still memoised
   because that branch never changes mid-process. The per-call cost is
   a single schema lookup against an already-cached description.

2. ExecuteTask::add() tokenised the human-friendly CLI input with
   `explode(' ', $data, 2)`, which split a quoted command path with
   embedded spaces in half — e.g. `"/usr/local/bin/My Tool" arg1` ended
   up with the path mangled across `command` and `params[0]`. Switched
   to `str_getcsv` with space as the delimiter and double-quote as the
   enclosure, so quoted command paths survive intact. The plain
   `cmd arg1 arg2` shape continues to work the same way it did before.

   Two regression tests:
   - testAddPreservesQuotedCommandPathWithSpaces — quoted path round-trip
   - testAddTokenizesPlainSpaceSeparatedArgs — bw compat for the simple case

3. docs/guide/operations.md is a new ops-first page covering: sizing
   workers, supervisor / systemd unit shapes, monitoring signals worth
   alerting on (stale workers, backlog growth, per-task failure rate),
   failure-handling workflow (admin dashboard, queue retry, the
   workaround dead-letter pattern until a formal DLQ ships), schema
   migrations on live workers (the captureOutput re-check above lets
   you add columns without restarting workers), multi-server pitfalls,
   and common task-author traps. Linked from /guide/ and the sidebar.

phpunit (186/186 + 7 skipped), phpstan, phpcs all clean.
@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.01%. Comparing base (d3ad8f4) to head (34eba2e).
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #496      +/-   ##
============================================
+ Coverage     77.55%   78.01%   +0.45%     
+ Complexity      972      971       -1     
============================================
  Files            45       45              
  Lines          3262     3262              
============================================
+ Hits           2530     2545      +15     
+ Misses          732      717      -15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dereuromark dereuromark merged commit 5854c79 into master May 13, 2026
16 checks passed
@dereuromark dereuromark deleted the queue-bug-batch branch May 13, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants