Skip to content

rwsite/wp-queue

Repository files navigation

WP Queue Logo

WP Queue

Laravel Horizon-like queue manager for WordPress
Simple, powerful, and modern background job processing.

Latest Version PHP Version Build Status Code Coverage License

Features β€’ Installation β€’ Quick Start β€’ Admin UI β€’ REST API β€’ Testing β€’ RU version


Features

  • πŸš€ Laravel-style API β€” Clean, fluent job dispatching with PHP 8 attributes
  • πŸ“¦ Multiple Drivers β€” Database, Redis, Memcached, Sync (auto-detection)
  • πŸ”„ Auto Retries β€” Exponential backoff for failed jobs
  • ⏰ Scheduling β€” Cron-like job scheduling
  • πŸ‘οΈ WP-Cron Monitor β€” View, run, pause, resume, edit cron events
  • πŸ“Š Dashboard β€” Beautiful admin UI with statistics
  • πŸ”Œ REST API β€” Full API for integrations
  • πŸ’» WP-CLI β€” Complete command-line interface
  • 🌍 i18n Ready β€” Translations included (Russian)

Requirements

  • PHP 8.3+
  • WordPress 6.0+

Installation

  1. Clone or download to wp-content/plugins/wp-queue
  2. Run composer install
  3. Activate the plugin

Quick Start

Create a Job

use WPQueue\Jobs\Job;
use WPQueue\Attributes\{Schedule, Queue, Timeout, Retries};

#[Schedule('hourly')]
#[Queue('imports')]
#[Timeout(120)]
#[Retries(5)]
class ImportProductsJob extends Job
{
    public function __construct(
        private array $productIds
    ) {
        parent::__construct();
    }

    public function handle(): void
    {
        foreach ($this->productIds as $id) {
            // Import logic here
        }
    }
    
    public function failed(\Throwable $e): void
    {
        // Handle failure
        error_log('Import failed: ' . $e->getMessage());
    }
}

Dispatch Jobs

use WPQueue\WPQueue;

// Dispatch to queue
WPQueue::dispatch(new ImportProductsJob([1, 2, 3]));

// With delay (seconds)
WPQueue::dispatch(new ImportProductsJob($ids))->delay(60);

// To specific queue
WPQueue::dispatch(new ImportProductsJob($ids))->onQueue('high-priority');

// Synchronous (bypass queue)
WPQueue::dispatchSync(new ImportProductsJob($ids));

// Chain jobs
WPQueue::chain([
    new FetchProductsJob(),
    new ImportProductsJob($ids),
    new NotifyAdminJob(),
])->dispatch();

// Batch jobs
WPQueue::batch([
    new ImportProductJob($id1),
    new ImportProductJob($id2),
    new ImportProductJob($id3),
])->dispatch();

Schedule Jobs

// In your plugin
add_action('wp_queue_schedule', function ($scheduler) {
    // Using attributes (automatic)
    $scheduler->job(ImportProductsJob::class);
    
    // Manual scheduling
    $scheduler->job(CleanupJob::class)->daily();
    
    // Custom interval
    $scheduler->job(CheckStopListJob::class)->everyMinutes(15);
    
    // Conditional
    $scheduler->job(SyncJob::class)
        ->hourly()
        ->when(fn() => get_option('sync_enabled'));
    
    // From settings
    $scheduler->job(BackupJob::class)
        ->interval(get_option('backup_interval', 'daily'));

    // One-time execution (at specific timestamp)
    $scheduler->job(OneTimeJob::class)->at(time() + 3600);
});

PHP 8 Attributes

#[Schedule]

#[Schedule('hourly')]                    // Fixed interval
#[Schedule('daily', setting: 'my_opt')]  // From wp_options

Available intervals: min, 5min, 10min, 15min, 30min, hourly, 2hourly, 3hourly, 6hourly, 8hourly, 12hourly, daily, twicedaily, weekly

#[Queue]

#[Queue('default')]    // Queue name
#[Queue('high')]       // Priority queue

#[Timeout]

#[Timeout(60)]   // 60 seconds
#[Timeout(300)]  // 5 minutes

#[Retries]

#[Retries(3)]   // Max 3 attempts
#[Retries(5)]   // Max 5 attempts

#[UniqueJob]

#[UniqueJob]           // Prevent duplicate jobs
#[UniqueJob(key: 'custom_key')]

Events (Hooks)

// Before job execution
add_action('wp_queue_job_processing', function($event) {
    // $event->job, $event->queue
});

// After successful execution
add_action('wp_queue_job_processed', function($event) {
    // $event->job, $event->queue
});

// On failure
add_action('wp_queue_job_failed', function($event) {
    // $event->job, $event->queue, $event->exception
});

// On retry
add_action('wp_queue_job_retrying', function($event) {
    // $event->job, $event->queue, $event->attempt, $event->exception
});

Queue Management

use WPQueue\WPQueue;

// Check status
WPQueue::isProcessing('default');   // bool
WPQueue::isPaused('default');       // bool
WPQueue::queueSize('default');      // int

// Control
WPQueue::pause('default');
WPQueue::resume('default');
WPQueue::cancel('default');   // Clear + pause
WPQueue::clear('default');    // Remove all jobs

// Logs
WPQueue::logs()->recent(100);
WPQueue::logs()->failed();
WPQueue::logs()->forJob(ImportProductsJob::class);
WPQueue::logs()->metrics();
WPQueue::logs()->clearOld(7);  // Clear logs older than 7 days

Admin UI

Access via WP Admin β†’ WP Queue

Tabs

Tab Description
Dashboard Stats (pending, running, completed, failed), queue management
Scheduled Jobs WP Queue jobs with "Run Now" button
Logs Execution history with filtering
WP-Cron All WordPress cron events monitoring
System Environment status and health check

WP-Cron Monitor

View and manage all WordPress cron events:

  • Filter by source (WordPress, WooCommerce, Plugins, WP Queue)
  • See overdue events
  • Run events manually
  • Delete scheduled events
  • View registered schedules

System Status

Health check and environment info:

  • PHP/WordPress versions
  • Memory limit and usage
  • WP-Cron status (disabled/alternate)
  • Loopback request check
  • Action Scheduler stats (if installed)
  • Timezone and time info

REST API

GET    /wp-json/wp-queue/v1/queues
POST   /wp-json/wp-queue/v1/queues/{queue}/pause
POST   /wp-json/wp-queue/v1/queues/{queue}/resume
POST   /wp-json/wp-queue/v1/queues/{queue}/clear
POST   /wp-json/wp-queue/v1/jobs/{job}/run
GET    /wp-json/wp-queue/v1/logs
POST   /wp-json/wp-queue/v1/logs/clear
GET    /wp-json/wp-queue/v1/metrics

# Cron & System
GET    /wp-json/wp-queue/v1/cron
POST   /wp-json/wp-queue/v1/cron/run
POST   /wp-json/wp-queue/v1/cron/delete
GET    /wp-json/wp-queue/v1/system

Queue Drivers

WP Queue supports multiple storage backends:

Driver Description Requirements
database Uses wp_options table (default) None
redis Redis server phpredis extension
memcached Memcached server memcached extension
sync Synchronous execution None
auto Auto-detect best available None

Configuration

Add to wp-config.php:

// Select queue driver
define('WP_QUEUE_DRIVER', 'redis'); // or 'memcached', 'database', 'sync', 'auto'

// Redis settings (compatible with redis-cache plugin)
define('WP_REDIS_HOST', 'redis');      // or '127.0.0.1'
define('WP_REDIS_PORT', '6379');
define('WP_REDIS_PREFIX', 'mysite_');  // optional
define('WP_REDIS_PASSWORD', 'secret'); // optional
define('WP_REDIS_DATABASE', 0);        // optional, 0-15

// Memcached settings
define('WP_MEMCACHED_HOST', '127.0.0.1');
define('WP_MEMCACHED_PORT', 11211);

Programmatic Configuration

use WPQueue\WPQueue;
use WPQueue\Contracts\QueueInterface;

// Set driver programmatically
WPQueue::manager()->setDefaultDriver('redis');

// Check available drivers
$drivers = WPQueue::manager()->getAvailableDrivers();
// ['database' => ['available' => true, 'info' => '...'], ...]

// Check if specific driver is available
if (WPQueue::manager()->isDriverAvailable('redis')) {
    WPQueue::manager()->setDefaultDriver('redis');
}

// Register custom driver
WPQueue::manager()->extend('sqs', function() {
    return new SqsQueue(['region' => 'us-east-1']);
});

Redis with redis-cache Plugin

If you use Redis Object Cache plugin, WP Queue will automatically use the same Redis connection settings. No additional configuration needed!

// These constants from redis-cache are automatically used:
// WP_REDIS_HOST, WP_REDIS_PORT, WP_REDIS_PASSWORD, WP_REDIS_DATABASE
// WP_REDIS_PREFIX, WP_REDIS_SCHEME, WP_REDIS_PATH, WP_REDIS_TIMEOUT

Migration from Action Scheduler

Before (Action Scheduler)

as_schedule_recurring_action(time(), HOUR_IN_SECONDS, 'my_hourly_task');

add_action('my_hourly_task', function() {
    // task code
});

After (WP Queue)

#[Schedule('hourly')]
class MyHourlyTask extends Job
{
    public function handle(): void
    {
        // task code
    }
}

// Register
add_action('wp_queue_schedule', fn($s) => $s->job(MyHourlyTask::class));

Comparison with Action Scheduler

Feature Action Scheduler WP Queue
Database 2 custom tables wp_options
API 20+ functions 1 facade
PHP version 7.4+ 8.3+
Registration Manual Attributes
Retry logic Complex #[Retries(3)]
UI Built-in Built-in
File count 50+ ~15

Testing

WP Queue uses a CI-first testing approach with comprehensive test coverage.

Unit Tests (Local)

Fast isolated tests without WordPress environment:

composer test:unit

Results: 69 tests, 130 assertions βœ…

E2E Tests (GitHub Actions)

Integration tests with real WordPress run automatically in CI:

  • βœ… WordPress latest (6.7+) + PHP 8.3
  • βœ… WordPress 6.7 + PHP 8.3

E2E tests run on every push to main/develop branches and in pull requests.

Code Quality

# Code style check
composer lint

# Run all tests
composer test

Note: Code coverage requires PCOV or Xdebug extension. In Docker environments, use:

docker exec wp_site-php composer lint
docker exec wp_site-php composer test:unit

See: tests/README.md

Example Plugin

See a complete working example: wp-queue-example-plugin

The example plugin demonstrates:

  • βœ… Creating custom jobs with PHP 8 attributes
  • βœ… Job scheduling with different intervals
  • βœ… Error handling and retries
  • βœ… Chain and batch processing
  • βœ… Queue management and monitoring
  • βœ… REST API integration
  • βœ… WP-CLI commands

Perfect for learning how to integrate WP Queue into your WordPress plugins!

License

GPL-2.0-or-later

About

πŸš€ Laravel-style queue processing for WordPress with modern background job management

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published