9

I've implemented a jobs queue a few days ago and I've been experiencing problems with duplication, I'm currently working with Redis and followed the Laravel's official tutorial.

In my case, whenever someone goes to the homepage, a job is sent to the queue, lets take this example:

HomeController's index() :

public function index()
{
    if(/*condition*/){
          //UpdateServer being the job
          $this->dispatch(new UpdateServer());
    }
}

Since this task takes about 10 seconds to complete, if there's n requests to my homepage while the task is being processed, there will be n more of the same job in queue, resulting in unexpected results in my Database.

So my question is, is there any way to know if a certain job is already in queue?

baao
  • 71,625
  • 17
  • 143
  • 203
Micael Sousa
  • 1,129
  • 3
  • 10
  • 16

4 Answers4

12

I know it's an old question but I find myself coming back here again and again from Google so I wanted to give it an answer. I wanted an easy way to view the jobs in the queue inside my Laravel application on a dashboard and used the following code.

$thejobs = array();

// Get the number of jobs on the queue
$numJobs = Redis::connection()->llen('queues:default');

// Here we select details for up to 1000 jobs
$jobs = Redis::connection()->lrange('queues:default', 0, 1000);

// I wanted to clean up the data a bit
// you could use var_dump to see what it looks like before this
// var_dump($jobs);
foreach ($jobs as $job) {

    // Each job here is in json format so decode to object form
    $tmpdata = json_decode($job);
    $data = $tmpdata->data;

    // I wanted to just get the command so I stripped away App\Jobs at the start
    $command = $this->get_string_between($data->command, '"App\Jobs\\', '"');
    $id = $tmpdata->id;

    // Could be good to see the number of attempts
    $attempts = $tmpdata->attempts;
    $thejobs[] = array($command, $id, $attempts);
}

// Now you can use the data and compare it or check if your job is already in queue

I don't recommend doing this, especially on page load such as the index page like the op has done. Most likely you need to rethink the way you are doing things if you need to have this code to check if a job is running.

The answer is specific to queues running Redis.

Matkey
  • 378
  • 4
  • 17
8

I know it's very old question, but I'm answering it for future Google users.

Since Laravel 8 there is the "Unique Jobs" feature - https://laravel.com/docs/8.x/queues#unique-jobs.

VG-Electronics
  • 230
  • 2
  • 16
3

For anyone wondering why

Queue::size('queueName');

is not the same size as

Redis::llen('queues:queueName');

is because Laravel uses 3 records to count the size of a queue, so if you want the true number of jobs in the queue you must do:

Redis::lrange('queues:queueName', 0, -1);
Redis::zrange('queues:queueName:delayed', 0, -1);
Redis::zrange('queues:queueName:reserved', 0, -1);

Now you can evaluate if your desired input is in one of those queues and act according.

iRynoh
  • 69
  • 7
0

You can do it in jobs handle function and skip work if another same job is scheduled

public function handle()
{
    $queue = \DB::table(config('queue.connections.database.table'))->orderBy('id')->get();
    foreach ($queue as $job){
        $payload = json_decode($job->payload,true);
        if($payload['displayName'] == self::class && $job->attempts == 0){
            // same job in queue, skip
            return ;
        }
    }

    // do the work
}