Using php-resque with Laravel
Jessie O’Brien wrote a great blog post explaining how he’d got php-resque setup with Laravel. I won’t rehash the background on php-resque or Laravel but instead I wanted to post because I did the exact same thing last week, but I went about it in a different way.
To begin, I ported the core of the php-resque run script (Resque.php) into an artisan task. This allows to run artisan which gives you the full laravel environment, but still run the php-resque workers. So to run the queue, it’s as simple as running
php artisan resque <queue> <logLevel> <interval> <pidFile>
/** * A Laravel Task which runs the PHP-Resque worker * This should be run using Artisan (php artisan resque) which will * then kick off a php-resque worker and listen for incoming messages * coming into the redis queues. */ class Resque_Task { /** * @param $arguments */ public function run($arguments) { Bundle::start('php-resque'); $queue = array_get($arguments, 0, 'default'); $logLevel = array_get($arguments, 1, 0); $interval = array_get($arguments, 2, 5); $pidFile = array_get($arguments, 3); $redis_config = Config::get("database.redis.default"); $backend = $redis_config['host'] . ':' . $redis_config['port']; // Connect to Redis Resque::setBackend($backend); $queues = explode(',', $queue); $worker = new Resque_Worker($queues); $worker->logLevel = $logLevel; if ($pidFile) { file_put_contents($pidFile, getmypid()) or die('Could not write PID information to ' . $pidFile); } fwrite(STDOUT, '*** Starting worker ' . $worker . "\n"); $worker->work($interval); } }
The next piece I wanted, was to be able to write each of the tasks which I execute on the queue as simple artisan tasks. That way I could test them in isolation and run them independantly of the queue just using artisan.
All I needed to do was create a simple php-resque Job which could run any artisan Task.
/** * A PHP-Resque Job which starts a Laravel Task. * This enables us to use PHP-Resque as robust processing queue * but still use Laravel Commands, bundles etc to do the work * */ class Laravel_Job { public function setUp() { } public function perform() { $task = array_get($this->args, 'task'); $arguments = array_get($this->args, 'arguments'); Command::run(array($task, $arguments)); } public function tearDown() { } }
So, that’s it. If I wanted to run a long-running artisan task, I can simply issue the following command (perhaps from one of my controllers in response to a user action).
Resque::enqueue('queue', 'Laravel_Job', array('task => 'LongRunningLaravelTask', 'arguments' => 'some param'), true);