Installation
composer require chrisboulton/php-resque
Ensure Redis is running locally or on your server (Resque requires Redis as a backend).
Basic Configuration
Create a Redis connection in config/database.php (if not using Laravel's default Redis):
'redis' => [
'client' => 'predis',
'options' => [
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
],
],
Configure Resque in config/resque.php (if using Laravel's config publishing):
php artisan vendor:publish --provider="Chrisboulton\Resque\ResqueServiceProvider"
Update the published config with your Redis connection name (e.g., 'connection' => 'redis').
First Job Define a job class:
namespace App\Jobs;
use Chrisboulton\Resque\Job\Job as ResqueJob;
class ProcessUser extends ResqueJob
{
protected $userId;
public function __construct($userId)
{
$this->userId = $userId;
}
public function perform()
{
// Your logic here (e.g., send email, process data)
\Log::info("Processing user {$this->userId}");
}
}
Enqueue a Job
use App\Jobs\ProcessUser;
use Chrisboulton\Resque\Facades\Resque;
Resque::enqueue(new ProcessUser(1));
Run a Worker
php artisan resque:work queue:*
(Replace queue:* with a specific queue name if needed.)
Dependency Injection Use constructor injection for job dependencies (e.g., repositories, services):
class SendWelcomeEmail extends ResqueJob
{
protected $user;
protected $mailer;
public function __construct(User $user, Mailer $mailer)
{
$this->user = $user;
$this->mailer = $mailer;
}
public function perform()
{
$this->mailer->send('welcome', [], $this->user->email);
}
}
Enqueue with bound dependencies:
Resque::enqueue(new SendWelcomeEmail($user, app(Mailer::class)));
Chaining Jobs
Use after or then to chain jobs (requires custom implementation or middleware):
Resque::enqueue(new ProcessUser(1))
->after(function () {
Resque::enqueue(new NotifyUser(1));
});
Alternative: Use a parent job class with perform() logic that enqueues follow-up jobs.
Delayed Jobs
Delay execution using delay:
Resque::enqueue(new ProcessUser(1))->delay(60); // 60 seconds
Job Prioritization
Use multiple queues (e.g., high, default, low) and process them in order:
php artisan resque:work high,default,low
Enqueue to a specific queue:
Resque::enqueue(new ProcessUser(1), 'high');
Horizontal Scaling Run multiple workers (e.g., one per core) to parallelize processing:
php artisan resque:work queue:* --daemon --pidfile=/tmp/resque.pid
Use --daemon for background operation and --pidfile for process management.
Queue Monitoring Check queue status with:
php artisan resque:status
List all jobs in a queue:
php artisan resque:list queue:high
Worker Events Listen to worker lifecycle events (e.g., job started/failed) via events:
// In EventServiceProvider
protected $listen = [
'Chrisboulton\Resque\Events\JobStarted' => [
'App\Listeners\LogJobStart',
],
'Chrisboulton\Resque\Events\JobFailed' => [
'App\Listeners\NotifyOnFailure',
],
];
Retry Logic
Implement retry() in your job to handle failures:
public function perform()
{
try {
// Risky operation
} catch (\Exception $e) {
$this->retry(3); // Retry up to 3 times
throw $e;
}
}
Queue Connection
Bind Resque to Laravel's queue system in AppServiceProvider:
public function boot()
{
Queue::extend('resque', function ($app) {
return new ResqueQueueService($app);
});
}
Then use Laravel's queue helpers:
dispatch(new ProcessUser(1))->onQueue('resque');
Job Serialization
Ensure job classes are serializable (avoid closures or non-serializable properties). Use __serialize()/__unserialize() if needed:
public function __serialize()
{
return ['userId' => $this->userId];
}
public function __unserialize(array $data)
{
$this->userId = $data['userId'];
}
Laravel Events as Jobs Convert Laravel events to async jobs:
// In EventServiceProvider
protected $listen = [
'user.created' => [
function (User $user) {
Resque::enqueue(new ProcessUser($user->id));
},
],
];
Redis Connection Issues
php artisan resque:status to debug.redis-cli monitor
Job Serialization Errors
Unable to serialize job or Class not found.__serialize()/__unserialize() for complex objects.Worker Stuck in "Working" State
kill -9 <PID>) and re-enqueue failed jobs. Use --timeout to limit worker runtime:
php artisan resque:work queue:* --timeout=300
Race Conditions
public function perform()
{
if (Redis::lock("process_user_{$this->userId}", 10)) {
try {
// Critical section
} finally {
Redis::unlock("process_user_{$this->userId}");
}
}
}
Memory Leaks
Allowed memory size exhausted.max_execution_time in php.ini or per-worker:
php artisan resque:work queue:* --max-execution-time=300
memory_get_usage() to monitor memory in jobs.Worker Logging Enable verbose logging for workers:
php artisan resque:work queue:* --verbose
Or configure logging in config/resque.php:
'log' => [
'enabled' => true,
'path' => storage_path('logs/resque.log'),
],
Job Inspection Dump job payloads for debugging:
public function perform()
{
\Log::debug('Job payload:', [
'userId' => $this->userId,
'args' => func_get_args(),
]);
}
Redis Debugging Inspect queues directly:
redis-cli LRANGE resque:queue:high 0 -1
redis-cli HGETALL resque:job:high:<job_id>
Worker PID Management
Use --pidfile to manage
How can I help you explore Laravel packages today?