laravel-queue-control maintained by campelo
Description
Queue orchestration and job control for Laravel. Cancel jobs, clear queues, pause workers, and manage job batches with ease.
Author
Last update
2026/02/15 13:32
(dev-master)
License
Downloads
0
Laravel Queue Control
Operational control for Laravel queues. Cancel jobs, clear queues, pause workers, and manage campaigns with ease.
Horizon vs Queue Control
| Laravel Horizon | Queue Control | |
|---|---|---|
| Focus | Observability | Operational Control |
| Monitors queues | Yes | Yes |
| Shows metrics | Yes | Yes |
| Cancel pending jobs | No | Yes |
| Cancel by campaign | No | Yes |
| Cancel by job type | No | Yes |
| Clear queues | No | Yes |
| Pause/Resume workers | No | Yes |
Use Horizon to watch. Use Queue Control to act.
The Problem
You dispatched 15,000 email jobs for a newsletter. Then you realized the email content was wrong. With Horizon, you can only watch them go out. With Queue Control:
php artisan queue-control:cancel --campaign=newsletter-42
Done. All pending jobs cancelled.
Requirements
- PHP 8.1+
- Laravel 10.x or 11.x
- Redis or Database queue driver
Installation
composer require campelo/laravel-queue-control
Publish and migrate:
php artisan vendor:publish --provider="Campelo\QueueControl\QueueControlServiceProvider"
php artisan migrate
Quick Start
1. Add the trait to your jobs
use Campelo\QueueControl\Traits\Cancellable;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
use Cancellable;
public function handle()
{
// Your job logic
}
}
2. Dispatch with campaign ID
// Group related jobs with a campaign ID
SendEmailJob::dispatch($user)->withCampaign('newsletter-42');
SendPushJob::dispatch($user)->withCampaign('newsletter-42');
3. Cancel when needed
# Cancel entire campaign (any job type)
php artisan queue-control:cancel --campaign=newsletter-42
# Cancel by job class
php artisan queue-control:cancel --job="App\Jobs\SendEmailJob"
# Cancel specific job by UUID
php artisan queue-control:cancel --uuid=550e8400-e29b-41d4-a716-446655440000
Key Features
Campaigns
Campaigns let you group different job types semantically:
// All these jobs belong to the same campaign
SendEmailJob::dispatch($user)->withCampaign('black-friday-2024');
SendSmsJob::dispatch($user)->withCampaign('black-friday-2024');
SendPushJob::dispatch($user)->withCampaign('black-friday-2024');
// Cancel all at once
QueueControl::cancelCampaign('black-friday-2024');
This is more powerful than batches because:
- Groups multiple job types
- Semantic naming (meaningful IDs)
- Closer to real-world operations
Queue Pause/Resume
# Pause - jobs are held, not lost
php artisan queue-control:pause emails
# Resume - processing continues
php artisan queue-control:resume emails
Dashboard
Access at /queue-control:
- Real-time queue statistics
- Job success/failure rates
- Campaign monitoring
- Queue controls
Configuration
// config/queue-control.php
return [
// Simple: list of user IDs
'allowed_users' => [1, 2, 3],
// Advanced: granular permissions per action
'permissions' => [
'pause' => ['admin', 'ops'],
'resume' => ['admin', 'ops'],
'cancel' => ['admin', 'ops', 'support'],
'clear' => ['admin'],
],
'dashboard' => [
'enabled' => true,
'path' => 'queue-control',
'middleware' => ['web', 'auth'],
],
];
Environment Variables
QUEUE_CONTROL_ALLOWED_USERS=1,2,3
QUEUE_CONTROL_DASHBOARD_PATH=queue-control
Artisan Commands
# List queues
php artisan queue-control:list
# Statistics
php artisan queue-control:stats
php artisan queue-control:stats --queue=emails --hours=24
# Clear queue
php artisan queue-control:clear emails
# Cancel jobs
php artisan queue-control:cancel --campaign=newsletter-42
php artisan queue-control:cancel --job="App\Jobs\SendEmailJob"
php artisan queue-control:cancel --batch=batch-uuid
php artisan queue-control:cancel --uuid=job-uuid
# Pause/Resume
php artisan queue-control:pause emails
php artisan queue-control:resume emails
# Cleanup old records
php artisan queue-control:cleanup
Using the Facade
use Campelo\QueueControl\Facades\QueueControl;
// Campaigns
QueueControl::cancelCampaign('newsletter-42');
QueueControl::isCampaignCancelled('newsletter-42');
// Jobs
QueueControl::cancelJob($uuid);
QueueControl::cancelJobsByClass(SendEmailJob::class);
// Queues
QueueControl::getQueues();
QueueControl::getQueueSize('emails');
QueueControl::clearQueue('emails');
QueueControl::pauseQueue('emails');
QueueControl::resumeQueue('emails');
QueueControl::isQueuePaused('emails');
// Batches
$batch = QueueControl::createBatch('Newsletter #42', 15000);
QueueControl::cancelBatch($batch->batch_id);
Granular Permissions
Queue Control supports fine-grained access control:
'permissions' => [
'pause' => ['admin'], // Only admins can pause
'resume' => ['admin', 'ops'], // Admin and ops can resume
'cancel' => ['admin', 'ops'], // Admin and ops can cancel
'clear' => ['admin'], // Only admins can clear
],
Works with:
- User IDs:
[1, 2, 3] - Roles:
['admin', 'ops'](requires Spatie Permissions or similar) - Gates: Define
queue-control.pause,queue-control.cancel, etc.
How It Works
Job Cancellation
- When you cancel, the ID is stored in cache (fast) and database (persistent)
- Before each job runs,
Queue::beforechecks if it's cancelled - Cancelled jobs are deleted without executing
Queue Pausing
- Pause sets a flag in cache
- Workers release jobs back to queue with delay
- Jobs are held, not lost
- Resume removes the flag
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/queue-control/dashboard |
Dashboard stats |
| GET | /api/queue-control/queues |
List queues |
| POST | /api/queue-control/queues/{queue}/clear |
Clear queue |
| POST | /api/queue-control/queues/{queue}/pause |
Pause queue |
| POST | /api/queue-control/queues/{queue}/resume |
Resume queue |
| POST | /api/queue-control/jobs/cancel |
Cancel by UUID |
| POST | /api/queue-control/jobs/cancel-by-class |
Cancel by class |
| GET | /api/queue-control/metrics |
Job metrics |
| GET | /api/queue-control/batches |
List batches |
| POST | /api/queue-control/batches/{id}/cancel |
Cancel batch |
Cleanup
Schedule cleanup to remove old records:
// Laravel 10
$schedule->command('queue-control:cleanup')->daily();
// Laravel 11
Schedule::command('queue-control:cleanup')->daily();
License
MIT License. See LICENSE for details.