2
votes

I am using Laravel 5 on a LAMP stack server running Ubuntu. I am using the queue system:

http://laravel.com/docs/master/queues

I can see from the docs that there is the ability to run queue:listen which will listen forever and process past and future items in the queue.

There is also queue:work which just processes the first item in the queue.

Is there a way to just process every item in the queue and then stop listening?

I only want to process the queue periodically so how can I setup a cron job that will process the queue and then as soon as everything in the queue has been done just exit?

2

2 Answers

2
votes

I was just looking at this, as well. I modified the built-in queue:work command to process the entire queue and exit.

php artisan make:console ProcessQueueAndExit

You can get the code at https://gist.github.com/jdforsythe/b8c9bd46250ee23daa9de15d19495f07

Or here it is, for permanence:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Carbon\Carbon;
use Illuminate\Queue\Worker;
use Illuminate\Contracts\Queue\Job;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class ProcessQueueAndExit extends Command {

  protected $signature = 'queue:workall {connection?} {--queue=} {--daemon} {--delay=} {--force} {--memory=} {--sleep=} {--tries=}';

  protected $description = 'Process all jobs on a queue and exit';
  protected $worker;

  public function __construct(Worker $worker) {
    parent::__construct();

    $this->worker = $worker;
  }

  public function handle() {
    if ($this->downForMaintenance() && ! $this->option('daemon')) {
      return $this->worker->sleep($this->option('sleep'));
    }

    $queue = $this->option('queue');
    $delay = $this->option('delay');
    $memory = $this->option('memory');
    $connection = $this->argument('connection');

    // keep processing until there are no more jobs returned
    do {
      $response = $this->runWorker(
        $connection, $queue, $delay, $memory, $this->option('daemon')
      );

      if (! is_null($response['job'])) {
        $this->writeOutput($response['job'], $response['failed']);
      }
    } while (! is_null($response['job']));
  }

  protected function runWorker($connection, $queue, $delay, $memory, $daemon = false) {
    if ($daemon) {
      $this->worker->setCache($this->laravel['cache']->driver());

      $this->worker->setDaemonExceptionHandler(
        $this->laravel['Illuminate\Contracts\Debug\ExceptionHandler']
      );

      return $this->worker->daemon(
        $connection, $queue, $delay, $memory,
        $this->option('sleep'), $this->option('tries')
      );
    }

    return $this->worker->pop(
      $connection, $queue, $delay,
      $this->option('sleep'), $this->option('tries')
    );
  }

  protected function writeOutput(Job $job, $failed) {
    if ($failed) {
      $this->output->writeln('<error>['.Carbon::now()->format('Y-m-d H:i:s').'] Failed:</error> '.$job->getName());
    }
    else {
      $this->output->writeln('<info>['.Carbon::now()->format('Y-m-d H:i:s').'] Processed:</info> '.$job->getName());
    }
  }

  protected function downForMaintenance() {
    if ($this->option('force')) {
        return false;
    }
    return $this->laravel->isDownForMaintenance();
  }
}
1
votes

I use this, in a command file:

$queue = Queue::connection('yourqueueconnection');

while ($entry = $queue->pop()) {
    // your task
}