Skip to content

Releases: dereuromark/cakephp-queue

8.14.0

14 May 02:02
d777481

Choose a tag to compare

Fixes

  • QueueProcessesTable::add() now evicts stale (pid, server) rows whose heartbeat is older than the new Queue.staleHeartbeatThreshold (default 90s) before inserting, fixing the worker crash-loop on containerized deployments (Docker/FrankenPHP). When the killed worker's row survived and the new worker tried to register with the same recycled PID, the unique-index collision threw a QueryException that the existing PersistenceFailedException catch in Processor::run() didn't handle (#493).
  • Idle-poll heartbeat output is now suppressed unless --verbose is set, so a worker waiting for jobs no longer floods stdout/log with "Looking for Job …" / "nothing to do, sleeping." lines on every loop iteration (#491).
  • Processor::captureOutput() no longer caches 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. Explicit Queue.captureOutput config is still memoised (that branch never changes mid-process); auto-detect now re-checks per call (#496).
  • ExecuteTask::add() no longer mangles quoted command paths with embedded spaces. explode(' ', ...) split "/usr/local/bin/My Tool" arg1 across command and params[0]; switched to str_getcsv with space delimiter so quoted paths survive intact. The plain cmd arg1 arg2 shape continues to work unchanged (#496).
  • QueueController::index() caps the rendered pending/scheduled lists at Queue.adminDetailsLimit (default 200) to avoid OOM on realistic backlogs. With thousands of pending or failed-and-retried rows the dashboard previously crashed via DebugKit's Variables panel serialising every view variable. Aggregate counts on the tiles keep reflecting the true totals; truncated lists get a "Showing N most recent of M" notice with a pre-filtered link to the QueuedJobs admin (#497).

Improvements

  • New --force (-f) option on bin/cake queue worker clean wipes every queue_processes row regardless of the heartbeat threshold (#492). Recovery path for the same container-restart scenario above when an operator wants a one-shot manual reset.

  • Queue.adminBackUrl (with optional Queue.adminBackLabel) makes the admin layout's "Back to App" header link configurable, so installations can point users back to a non-default app URL. Mirrors the same pattern used by cakephp-audit-stash, cakephp-bouncer and cakephp-databaselog.

  • workerkey is now the canonical worker identity in queue_processes (#494). The unique (pid, server) index has been dropped (re-added as a non-unique index for query performance) because PID is not a stable identity — the OS recycles low PIDs across container restarts. update(), remove(), and endProcess() look up by workerkey (already uniquely indexed); when multiple rows share a PID, the most recently heartbeated row is targeted. Migration required: run bin/cake migrations migrate -p Queue.

  • createJob() gains an opt-in unique option that dedups fan-out enqueues against the existing reference-keyed pending job (#498). First call inserts as usual; subsequent calls while the original is still pending return the existing entity without inserting. Once it completes, the next call inserts a fresh row, so scheduled re-runs continue to enqueue normally. Requires reference to be set (throws InvalidArgumentException otherwise); default is false so existing callers are unchanged.

    $queuedJobsTable->createJob(
        'VolunteerCheckOutReminder',
        ['account_uuid' => $accountUuid],
        [
            'reference' => 'volunteer_check_out:' . $accountUuid,
            'unique' => true,
        ],
    );
  • Admin dashboard banner gains a red Queue Stalled state for "action required" signaling (#499). Triggers when the last heartbeat is older than Queue.dashboardStalledAfter (default 120s) with a pending backlog and no in-flight job, or when no worker has reported at all and there's a pending backlog or a stuck fetched job. The existing green Queue Running and yellow Queue Idle states are unchanged. When red, the banner expands with a diagnostic grid (last activity, workers/servers, pending count) and a one-line cause hint. Two new config keys: Queue.dashboardIdleAfter (60s default), Queue.dashboardStalledAfter (120s default).

Full Changelog: 8.13.0...8.14.0

8.13.0

03 May 15:51
8a7c89c

Choose a tag to compare

⚠️ Breaking Changes

  • Queue.executeAllowedCommands is now required when debug=false for any deployment that runs Queue.Execute jobs (#485). With the key unset or empty in production, every Execute job is rejected before exec() is invoked. Migration — add to config/app.php (or app_local.php):

    'Queue' => [
        'executeAllowedCommands' => [
            'bin/cake',
            // '/usr/bin/php',
        ],
    ],

    In dev (debug=true) the allow-list is ignored, so local environments are unaffected. See config/app.example.php and docs/sections/tasks/execute.md.

  • ExecuteTask now escapes the command and each params entry per token via escapeshellarg() instead of escapeshellcmd() (#485). Each value is wrapped as a single shell argument, which closes argument-injection paths but means callers that previously packed multiple tokens into a single entry must split them across the array. Migration:

    // before
    ['command' => 'bin/cake importer run', 'params' => ['--limit 10']]
    
    // after
    ['command' => 'bin/cake', 'params' => ['importer', 'run', '--limit', '10']]

    See docs/sections/upgrading.md for the full note.

Fixes

  • EmailTask::run() now restricts unserialize() to the configured Message subclass via allowed_classes, closing a gadget-chain risk on legacy raw-serialized settings (#484). Modern array-path callers using EmailTask::serialize() are unaffected.
  • Pagination element now uses escapeTitle instead of the broader escape so URL/class/title attributes stay HTML-escaped while the title text can still carry icon markup (#483).

Full Changelog: 8.12.0...8.13.0

8.12.0

30 Apr 15:54

Choose a tag to compare

Security adjustment

  • Queue.adminAccess is now required to access the admin backend at /admin/queue/.... The host application MUST set it to a Closure that returns literal true to grant access — anything else (unset, non-Closure, returns false, returns a truthy non-bool, throws) yields a 403. The admin UI can trigger jobs (via AddFromBackendInterface tasks), reset / remove queued jobs, and terminate workers; accidental exposure is harmful, so the default policy is now deny.

    Migration — add to config/bootstrap.php:

    use Cake\Core\Configure;
    use Cake\Http\ServerRequest;
    
    Configure::write('Queue.adminAccess', function (ServerRequest $request): bool {
        $identity = $request->getAttribute('identity');
        return $identity !== null && in_array('admin', (array)$identity->roles, true);
    });

    See docs/sections/admin_dashboard.md for the Authorization subsection. adminAccess is independent of Queue.standalone — the gate runs in both modes.

Improvements

  • Sweep stale queue_processes rows on worker startup (#480) — workers now clear orphan rows on launch instead of leaving them around for the timeout sweep.

Full Changelog: 8.11.0...8.12.0

8.11.0

27 Apr 13:24
39cf2e7

Choose a tag to compare

Fixes

  • Fix Queue::addJob() silently no-op'ing when a task's run() did not actually queue a job. The return value now reliably reflects whether a job was created. (#478)

Improvements

  • Add Queue.workerLifetimeJitter config option to stagger worker shutdowns and avoid thundering-herd restarts when many workers are spawned together. (#476)
  • Refactor admin UI to be CSP-compatible: inline <script> blocks now use nonces and inline onclick handlers were removed. (#477)
  • Move mobile-nav background image from an inline style attribute to a CSS class so the admin UI works under strict CSP. (#479)

Full Changelog: 8.10.2...8.11.0

8.10.2

17 Apr 18:51
5410512

Choose a tag to compare

Fixes

  • Fix EmailTask calling undefined methods on Mailer/Message when queued payloads contained keys from a serialized Cake\Mailer\Message (htmlMessage, textMessage, appCharset). These are now routed to the correct Message setters (setBodyHtml, setBodyText, setCharset fallback). (#474, fixes #473)
  • Fix EmailTask throwing Unknown named parameter when settings.headers or the readReceipt address setting was an associative map. (#474)

Full Changelog: 8.10.1...8.10.2

8.10.1

17 Apr 14:33
6eda87a

Choose a tag to compare

Fixes

  • Fix EmailTask throwing Unknown named parameter on PHP 8+ when queued payloads used CakePHP's associative ['email' => 'Name'] address-map format for to, from, cc, bcc, or replyTo. Previously-working payload formats (string, ['email', 'Name'] tuple, legacy wrapped [['email' => 'Name']]) are unchanged. (#472, fixes #471)

Full Changelog: 8.10.0...8.10.1

8.10.0

02 Apr 14:57

Choose a tag to compare

Modern Isolated Admin Dashboard (#461)

This release introduces a modern, self-contained admin dashboard for the Queue plugin that is completely isolated from the host application's CSS/JS.

Key Features

  • Bootstrap 5.3.3 + Font Awesome 6.7.2 via CDN with SRI hashes
  • Isolated base controller (QueueAppController) that extends Cake\Controller\Controller directly
  • Default enabled - the new layout is used automatically (can be disabled)
  • Mobile responsive - offcanvas navigation for mobile devices
  • Backwards compatible - can revert to app's layout via config

Configuration Options

'Queue' => [
    // Layout for admin pages:
    // - null (default): Uses 'Queue.queue' isolated Bootstrap 5 layout
    // - false: Disables plugin layout, uses app's default layout
    // - string: Uses specified layout
    'adminLayout' => null,

    // Auto-refresh dashboard every N seconds (0 = disabled)
    'dashboardAutoRefresh' => 30,
],

Dashboard Features

  • Status banner showing queue running/idle state
  • Statistics cards for pending, scheduled, running, and failed jobs
  • Pending/scheduled jobs tables with inline actions
  • Job statistics with Chart.js visualization
  • Trigger jobs section for addable tasks
  • Configuration display
  • Sidebar navigation with quick actions
  • Mobile offcanvas navigation

Stats Page Improvements

  • Fixed Chart.js infinite vertical expansion issue
  • Job type filter now uses query parameters (supports job types with slashes)
  • Added back button when viewing specific job type stats

Full Changelog: 8.9.1...8.10.0

dashboard_queue

8.9.1

17 Mar 21:54

Choose a tag to compare

Fixes

  • Fixed hidden dependency on Tools plugin in admin templates by adding runtime fallbacks for relLengthOfTime() (falls back to CakePHP's timeAgoInWords()) and Format->ok() (uses element with fallback)
  • Fixed hidden dependency on Shim plugin in JsonableBehavior by adding local ArrayType class

Full Changelog: 8.9.0...8.9.1

8.9.0

29 Jan 18:35
798f9af

Choose a tag to compare

Improvements

  • Add optional output capture for queue jobs

Full Changelog: 8.8.0...8.9.0

8.8.0

11 Jan 03:11
1418afb

Choose a tag to compare

Improvements

  • varexporter v7 support
  • Add Queue.Job.* lifecycle events with optional Sentry bridge

Full Changelog: 8.7.0...8.8.0