oeltimacreation/php-simplequeue

A lightweight, framework-agnostic background job queue system for PHP with Redis and database drivers

Maintainers

Package info

github.com/oeltimacreation/php-simplequeue

pkg:composer/oeltimacreation/php-simplequeue

Transparency log

Statistics

Installs: 451

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 0

1.10.0 2026-08-18 12:44 UTC

README

A small, lightweight, framework-agnostic PHP library for durable background job processing.

SimpleQueue is designed to be physically compact and easy to hold in one head while delivering enterprise-grade job guarantees. Storage is authoritative for job persistence, state transitions, and leases, while Redis or database polling acts as the delivery notification layer.

Key Features

Feature Description
Zero Heavy Dependencies Requires only psr/container and psr/log. Redis and PDO remain optional.
Two-Layer Architecture Authoritative storage (PDO / In-Memory) decoupled from notification drivers (Redis / DB / In-Memory).
Scheduled Dispatch Delay initial job availability using dispatchAfter(), dispatchAt(), or $availableAt.
At-Least-Once Delivery & Fencing Worker claims use worker IDs and lease tokens to fence completion, retry, and progress updates.
Idempotency & Deduplication dispatchIdempotent() prevents duplicate active jobs for a given request ID.
Bounded Queue Repair Built-in QueueReconciler detects lost notifications and repairs stale leases safely.
Middleware & Execution Context Wrap handlers in ordered middleware with typed job identity, payload, queue, and attempt context.
Typed Worker Events Stable readonly lifecycle event objects retain the existing string/array listener compatibility layer.
Failed-Job Administration List, inspect, re-queue, and purge failed jobs through AdminManager.
PHP 8.2+ Modernization Strict types everywhere (declare(strict_types=1)), readonly value objects, and PHPStan Level 9 strict compliance.

Requirements

  • PHP: 8.2 or later
  • Database (Optional): PDO (MySQL, PostgreSQL, SQLite) for durable persistence
  • Redis / Valkey (Optional): Redis 7+ or Valkey 8+ with predis/predis:^3 for Redis delivery

Installation

composer require oeltimacreation/php-simplequeue

# Optional: install Predis only if using the Redis queue driver
composer require predis/predis

Create the background_jobs table using the schema for your database in the database guide.

Quick Start

The fastest way to see the complete dispatch → process → inspect lifecycle is using the in-memory driver and storage:

<?php

declare(strict_types=1);

use Oeltima\SimpleQueue\Contract\JobHandlerInterface;
use Oeltima\SimpleQueue\Driver\InMemoryQueueDriver;
use Oeltima\SimpleQueue\JobDispatcher;
use Oeltima\SimpleQueue\JobRegistry;
use Oeltima\SimpleQueue\QueueManager;
use Oeltima\SimpleQueue\Storage\InMemoryJobStorage;
use Oeltima\SimpleQueue\Worker;
use Oeltima\SimpleQueue\WorkerOptions;

final class WelcomeEmailHandler implements JobHandlerInterface
{
    public function handle(int $jobId, array $payload, ?callable $progress = null): mixed
    {
        if ($progress !== null) {
            $progress(percent: 100, message: 'Email sent');
        }

        return ['recipient' => $payload['email']];
    }
}

// 1. Initialize components
$storage = new InMemoryJobStorage();
$queues = new QueueManager(driver: new InMemoryQueueDriver());
$registry = new JobRegistry();
$registry->register(type: 'email.welcome', handler: WelcomeEmailHandler::class);

// 2. Dispatch a job
$dispatcher = new JobDispatcher(storage: $storage, queueManager: $queues);
$jobId = $dispatcher->dispatch(type: 'email.welcome', payload: ['email' => 'ada@example.test']);

// 3. Process the job with a worker
$workerOptions = WorkerOptions::fromArray(['lock_file' => null]);
$worker = new Worker(
    storage: $storage,
    queueManager: $queues,
    registry: $registry,
    queue: 'default',
    options: $workerOptions,
);
$worker->processOne();

// 4. Inspect job status
echo $dispatcher->getStatus(jobId: $jobId)?->status->value; // 'completed'

For runnable examples with durable databases and Redis, see examples/.

Scheduled Dispatch

Delay a job's first availability using dispatchAfter(), dispatchAt(), or the $availableAt parameter:

// Dispatch 5 minutes into the future
$jobId = $dispatcher->dispatchAfter(
    delaySeconds: 300,
    type: 'email.welcome',
    payload: ['email' => 'ada@example.test'],
);

// Dispatch at a specific timestamp
$jobId = $dispatcher->dispatchAt(
    timestamp: strtotime('tomorrow 09:00'),
    type: 'email.welcome',
    payload: ['email' => 'ada@example.test'],
);

// Dispatch via optional availableAt parameter
$jobId = $dispatcher->dispatch(
    type: 'email.welcome',
    payload: ['email' => 'ada@example.test'],
    availableAt: new DateTimeImmutable('+1 hour'),
);

Quick API Reference

Class Key Methods Description
JobDispatcher dispatch(), dispatchAfter(), dispatchAt(), dispatchBatch(), dispatchIdempotent(), getStatus() Main entry point for enqueueing jobs and querying status.
Worker run(), processOne(), withOptions() Worker loop executing jobs with signal handling and lease heartbeat.
JobMiddlewareRegistry register(), all(), clear() Ordered worker middleware registration.
QueueManager create(), redis(), database() Driver factory supporting auto-selection and driver resolution.
JobRegistry register(), get(), has() Handler registry mapping job type strings to JobHandlerInterface classes.
AdminManager listFailed(), inspectFailed(), requeueFailed(), purgeFailed() Failed-job and dead-letter operations.
PdoJobStorage createJobs(), claimNextAvailable(), markCompleted(), markFailed(), scheduleRetry() Durable database persistence implementing JobStorageInterface.

Documentation Index

  • Getting Started — Durable database setup and worker setup
  • Database Guide — Schemas, indexes, transactions, and idempotency
  • Configuration — Driver auto-selection, polling, and worker options
  • Operations — Deployment, supervisor configuration, monitoring, and repair
  • Architecture — Two-layer model, lifecycle state machine, and lease fencing
  • Extending — Custom handlers, storage implementations, and drivers
  • Upgrading — Version upgrade instructions and migration guides
  • Runnable Examples — Sample catalogue and benchmark scripts

Delivery Guarantees

SimpleQueue provides at-least-once delivery. Handlers must be written to be idempotent (e.g. using database transaction unique constraints or payment reference checks).

For cross-process request deduplication, use dispatchIdempotent() along with the unique request ID index described in the database guide.

Development & Quality Gates

composer check        # Full quality check (tests, PHPStan Level 9, PHPCS, quality ratchet)
composer test         # Run PHPUnit test suite
composer phpstan      # Run static analysis
composer cs-check     # Run code style check
composer cs-fix       # Auto-fix code style issues

See CONTRIBUTING.md for contribution guidelines and LICENSE for license details.