kalider/php-simple-queue

There is no license information available for the latest version (1.0.0) of this package.

php simple queue with small footprint

Maintainers

Package info

github.com/kalider/php-simple-queue

pkg:composer/kalider/php-simple-queue

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-08-28 03:13 UTC

This package is auto-updated.

Last update: 2026-08-28 03:18:23 UTC


README

A lightweight, modular queue library for PHP 7.0+ implementing the Adapter Pattern and Factory Pattern. Supports MySQL (PDO) and Redis (phpredis), featuring exponential backoff, procedural job execution, and PSR-3 logging (Monolog).

๐Ÿ—๏ธ Architecture & Design Patterns

  • Adapter Pattern:
    • PhpSimpleQueue\Queue: The client interface/wrapper implementing QueueInterface.
    • PhpSimpleQueue\Adapters\QueueAdapterInterface: The common contract for queue drivers.
    • PhpSimpleQueue\Adapters\MysqlAdapter: MySQL storage adapter using PDO with atomic locking tokens.
    • PhpSimpleQueue\Adapters\RedisAdapter: Redis storage adapter using phpredis with atomic Lua scripts.
  • Factory Pattern:
    • PhpSimpleQueue\Factories\ConnectionFactory: Assembles and returns database/cache connection instances (PDO or Redis).
    • PhpSimpleQueue\Factories\QueueFactory: Instantiates configured Queue instances with the corresponding adapter and connection.

๐Ÿš€ Features

  • PHP 7.0+ Compatible: Works on PHP 7.0 through PHP 8.x.
  • Dual Storage Adapters:
    • MySQL (PDO): Safe concurrency using atomic lock tokens (reserved_by & reserved_at).
    • Redis (phpredis): Atomic pop using Lua scripts and Sorted Sets (ZSET) for delayed processing.
  • Delayed Jobs: Built-in support for delaying job execution by $N$ seconds.
  • Exponential Backoff: Automatic retry with exponential delay (pow(2, attempts) * 10 seconds) up to a max attempt threshold (default: 5).
  • Dead Letter / Failed Queue: Permanently failed jobs are moved to failed_jobs table (MySQL) or jobs:failed list (Redis).
  • Procedural Job Dispatching: Execute global functions or callables via call_user_func_array().
  • PSR-3 Logging: Fully compatible with PSR-3 loggers like Monolog.
  • Code Style (PHP-CS-Fixer): Pre-configured PSR-12 / PSR-2 code formatting and checking.

๐Ÿ“ฆ Installation

Install via Composer:

composer require kalider/php-simple-queue

๐Ÿ—„๏ธ Database Setup (MySQL)

If using the MySQL adapter, create the jobs and failed_jobs tables:

CREATE TABLE IF NOT EXISTS `jobs` (
    `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    `payload` LONGTEXT NOT NULL,
    `available_at` INT UNSIGNED NOT NULL,
    `created_at` INT UNSIGNED NOT NULL,
    `reserved_at` INT UNSIGNED NULL DEFAULT NULL,
    `reserved_by` VARCHAR(255) NULL DEFAULT NULL,
    INDEX `idx_queue_reservation` (`reserved_at`, `available_at`),
    INDEX `idx_reserved_by` (`reserved_by`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS `failed_jobs` (
    `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    `payload` LONGTEXT NOT NULL,
    `failed_at` INT UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

๐Ÿ› ๏ธ Usage

1. Define Your Job Function

function send_welcome_email(array $data)
{
    echo "Sending email to {$data['name']} ({$data['email']})...\n";
}

2. Creating Queue via QueueFactory

A. MySQL Queue (via Config Array)

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PhpSimpleQueue\Factories\QueueFactory;

$queue = QueueFactory::create([
    'driver'   => 'mysql',
    'host'     => '127.0.0.1',
    'port'     => 3306,
    'database' => 'your_database',
    'username' => 'root',
    'password' => 'secret',
    'table'    => 'jobs',         // optional, default: 'jobs'
    'failed_table' => 'failed_jobs', // optional, default: 'failed_jobs'
]);

// Push immediate job
$queue->push('send_welcome_email', ['email' => 'john@example.com', 'name' => 'John Doe']);

// Push delayed job (delay 60 seconds)
$queue->push('send_welcome_email', ['email' => 'jane@example.com', 'name' => 'Jane Doe'], 60);

B. MySQL Queue (with Existing PDO Instance)

$pdo = new PDO('mysql:host=127.0.0.1;dbname=your_database', 'root', 'secret');

$queue = QueueFactory::create([
    'pdo' => $pdo, // or 'connection' => $pdo
]);

C. Redis Queue (via Config Array)

$queue = QueueFactory::create([
    'driver'   => 'redis',
    'host'     => '127.0.0.1',
    'port'     => 6379,
    'password' => null,     // optional
    'database' => 0,        // optional
    'queue'    => 'default', // optional, default: 'jobs'
]);

$queue->push('send_welcome_email', ['email' => 'john@example.com', 'name' => 'John Doe']);

D. Redis Queue (with Existing Redis Instance)

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$queue = QueueFactory::create([
    'redis' => $redis, // or 'connection' => $redis
]);

3. Manual Adapter Instantiation (Adapter Pattern)

You can also instantiate adapters directly without the factory:

use PhpSimpleQueue\Adapters\MysqlAdapter;
use PhpSimpleQueue\Queue;

$adapter = new MysqlAdapter($pdo, 'jobs', 'failed_jobs');
$queue = new Queue($adapter);

4. Running the Worker (with Monolog)

Create a daemon worker script (e.g., worker.php):

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PhpSimpleQueue\Factories\QueueFactory;
use PhpSimpleQueue\Worker;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// 1. Setup PSR-3 Logger (Monolog)
$logger = new Logger('queue_worker');
$logger->pushHandler(new StreamHandler(__DIR__ . '/worker.log', Logger::INFO));
$logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));

// 2. Setup Queue via Factory
$queue = QueueFactory::create([
    'driver'   => 'mysql',
    'host'     => '127.0.0.1',
    'database' => 'your_database',
    'username' => 'root',
    'password' => 'secret',
]);

// 3. Start Worker Daemon
$worker = new Worker($queue, $logger, 3); // sleep 3 seconds when queue is empty
$worker->daemon();

Run the worker:

php worker.php

๐Ÿ”„ Failure & Retry Mechanism

  • When an unhandled exception or error occurs:
    1. An ERROR entry is logged with the error message and job ID.
    2. The attempt count is incremented (attempts + 1).
    3. If attempts < 5, re-queued with exponential backoff: $$\text{Delay} = 2^{\text{attempts}} \times 10\text{ seconds}$$
    4. If attempts $\ge 5$, the job is permanently marked as failed and moved to failed_jobs table (MySQL) or jobs:failed list (Redis).

๐Ÿงน Code Style & Linting (PHP-CS-Fixer)

Projek ini dilengkapi konfigurasi PHP-CS-Fixer dengan standar PSR-12 / PSR-2.

Periksa format kode tanpa mengubah file (dry-run & diff):

composer cs:check

Perbaiki format kode secara otomatis:

composer cs:fix

๐Ÿงช Running Tests

./vendor/bin/phpunit
# or
composer test

๐Ÿ“„ License

MIT License.