Skip to content

CodeIgniter Jobs

Job scheduling and queue processing for CodeIgniter 4. Describe work with a fluent, immutable builder, dispatch it to one of five interchangeable queue backends, and process it with a resilient worker — real timeouts, retries with backoff, HMAC-signed envelopes, idempotency and per-queue handler allowlists.

Get started View on GitHub

v3.0 is a single, clean architecture

The legacy mutable Job builder, the V1 Scheduler, the performance loggers, the NotificationService/email integration, the QueueManager and the JobsLogModel were all removed. Upgrading from v1? See Migration v1 → v3.

Features

  • Fluent, immutable definitions


    Jobs::define() opens a throwaway JobBuilder; the result is a readonly JobDefinition value object. No mutable god-object.

    Jobs & Builder

  • Five backends, one contract


    sync, database, redis, beanstalk and serviceBus all implement the same lease-based QueueBackend — at-least-once delivery on every persistent backend.

    Queues & Workers

  • Secure by default


    HMAC-signed envelopes, a per-queue handler allowlist, deny-by-default shell, an event allowlist and an anti-SSRF url handler.

    Security

  • Real timeouts & retries


    pcntl interrupts even CPU-bound code at the deadline; retries with none / fixed / exponential backoff and a configurable budget.

    Retries

  • Cron scheduling


    Frequency helpers (dailyAt, everyMinute, hourly, …), topological dependsOn() ordering and environment gating.

    Scheduling

  • Production-ready operations


    Circuit breaker, per-queue rate limits, graceful shutdown, a lease reaper, metrics and an opt-in dead-letter helper.

    Operations

Quick start

1. Define and dispatch a job

use Daycry\Jobs\Jobs;

$id = Jobs::define('command', 'app:report')
    ->named('daily-report')
    ->queue('reports')
    ->maxRetries(3)
    ->dispatch();

Jobs::define() opens a fluent JobBuilder; dispatch() enqueues the resulting immutable JobDefinition onto the configured backend and returns its backend-assigned id. Use toDefinition() to build a definition without enqueuing, and Jobs::backend(?string $name) to resolve a backend directly.

Note

With the zero-config default backend (sync), dispatch() runs the job inline and returns a synthetic sync-... id. Switch Config\Jobs::$worker to database, redis, beanstalk or serviceBus to actually enqueue for a separate worker process.

2. Run a worker

php spark jobs:queue:work reports

The worker leases one ready message at a time, verifies its signature, runs a single attempt, then acks on success or nacks (with backoff) / abandons on failure. Stop it gracefully with ++ctrl+c++ (SIGINT) or SIGTERM.

3. Schedule a recurring job

Register schedules in Config\Jobs::init():

public function init(\Daycry\Jobs\Cron\Scheduler $scheduler): void
{
    $scheduler->define('command', 'app:report')
        ->named('daily-report')
        ->dailyAt('02:00')
        ->queue('reports');
}

Then run the cron runner once per minute from your operating system's crontab:

* * * * * cd /var/www/app && php spark jobs:cronjob:run >> /dev/null 2>&1

Due definitions with a queue are enqueued; the rest run inline. See Quick Start for the full end-to-end tutorial, including a custom handler and envelope signing.

Core concepts

  • JobBuilderJobDefinition — the builder is a throwaway accumulator; the definition is an immutable value object that travels through the queue as a JobEnvelope.
  • Handlers implement JobHandlerInterface and receive a read-only JobContext — they never see the builder. Built-in keys: command, shell, closure, event, url.
  • Backends share one QueueBackend contract with at-least-once delivery, so the same definition works on any backend.
  • The worker runs a single attempt per fetch; retries are the backend's responsibility (requeue with backoff).

Contributions and feedback are welcome on GitHub. Released under the MIT License.