Ninj4df's avatar

Duplicate Jobs

hello guys. I have been researching this bug for hours, without any luck.

I have a problem, I dispatch a job on scheduler every 1 minute, but sometimes I can see the job being twice on the queue. The jobs are running from different queue workers at the same time. How is that possible?

I also use ShouldBeUnique interface on my job.

and on my scheduler I have:

$schedule->job(new MyJobName())->everyMinute();

Can someone help me, because I am so confused. Am i doing something wrong here?

0 likes
12 replies
Snapey's avatar

@mohamedtammam @jimmyaldape i dont think its that guys. withoutOverlapping only concerns running two instances of the same scheduled task. Since the scheduler's work is over in a fraction of a second (putting the job on the queue) then they will never overlap.

@ninj4df my first investigation would be to pause the queue workers and see if this job starts to build up in the queue (sounds like it will)

Snapey's avatar

sorry @jimmyaldape has the right idea, its the withoutOverlapping contract that you need to add to your job

confusing that there are two identically named functions in different places

Note that adding the contract to your job will not prevent the job being listed multiple times, but will ensure they cannot be executed at the same time by different workers

Ninj4df's avatar

And guys what's the difference between withoutOverlapping on Schedule VS ShouldBeUnique contract on jobs? Huge note here that all my scheduled actions are queued Jobs, does it still work with jobs? And also if you can explain why ShouldBeUnique does not work on my case?

Could someone clarify that guys? Thank you a lot for your time and your answers!

Snapey's avatar

withoutOverlapping on scheduled tasks just means don't start another instance of this scheduled task if a previous one is still running. You don't have any long running tasks, so this is irrelevant.

ShouldBeUnique might not work if you don't have a clear way to identify duplicate instances of the same job.

Ninj4df's avatar

@Snapey so withoutoverlapping is irellevant on my case if I understood well? Also i have jobs not commands or callbacks on scheduler, does it afftect it somehow?

Wasn't withoutOverlapping what you suggested me before? Sorry but I lost you :D Maybe I got confused on smthing .

Snapey's avatar

@Ninj4df If a job is placed on the queue, but there are no available queue workers for one minute, or a backlog on the queues, then after a minute, a second copy of the job is added to the queue.

How do you want to handle this?

  • Perform the first job and then immediately start the second job (then the job runs twice in the same minute)
  • perform the first job, and then when a worker picks up the second job, delete it because there is already one running.

The correct answer for you depends on what you hope to happen.

Ninj4df's avatar

@Snapey I am ok with both of them :) I just want to ensure that this job is not running multiple times simultaneously. What do you suggest me?

Ninj4df's avatar

@Snapey Ok, then I prefer the second one

"perform the first job, and then when a worker picks up the second job, delete it because there is already one running."

Snapey's avatar

@Ninj4df https://laravel.com/docs/11.x/queues#preventing-job-overlaps

When you add the middleware to the job, you are expected to provide an arbitrary key name which you can decide. In the example it uses the user ID but you could use a string

public function middleware(): array
{
    return [new WithoutOverlapping('not-to-be-overlapping-job-name')->dontRelease()];
}

You can release the job back to the queue, but you have said your preference is to delete it, so add dontRelease

edit: struck me that you could probably just use the name of the job

public function middleware(): array
{
    return [new WithoutOverlapping(get_class($this))->dontRelease()];
}

Please or to participate in this conversation.