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);