Recently I needed to create a FIFO (First In, First Out) queue in Laravel to run specific actions inside a long-running worker from outside the worker itself. I had two possibilities:
Database, creating a table, but I had also to create a Model, Service, Repository and many other things;
Redis, already installed.
Of course, I went with Redis, taking advantage of two main commands: RPUSH and LPOP.
Theory
The first one, RPUSH, will append an item to a given list (and create if it does not exist) and will be responsible for pushing new items to the list; LPOP, instead, will pop out the first item in the list, deleting it from our "queue". A quick visual explanation:
Code
Thanks to Laravel Redis facade we can use the Redis commands as static methods and, because LPOP will return false
if the list is empty, we can easily loop until there are no more items to process:
<?php
use Illuminate\Support\Facades\Redis;
// Define our queue name
$queueName = 'fifo';
// Put some items in our queue
// You can run this code outside your long-running worker
Redis::rpush($queueName, 'item1');
Redis::rpush($queueName, 'item2');
// ---------------------- somewhere else ----------------------
// Process until there are no more elements
// Note that will close when the queue is empty
while ($item = Redis::lpop($queueName)) {
echo 'Found: ' . $item . PHP_EOL;
}
// Output:
// "Found: item1"
// "Found: item2"
If you want to run it in a long-running worker, you'll need to slightly change the while
loop into something like this (or using a library like the great ReactPHP) to not stop the script even if the queue is empty:
<?php
use Illuminate\Support\Facades\Redis;
// Define our queue name
$queueName = 'fifo';
// Process until there are no more elements
while (true) {
if ($item = Redis::lpop($queueName)) {
echo 'Found: ' . $item . PHP_EOL;
}
}
// Output:
// "Found: item1"
// "Found: item2"