Laravel ShouldBeUnique doesn't make jobs to be unique
Asked Answered
C

0

6

I expected job marked with ShouldBeUnique interface to not be dispatched more than once. However all jobs are dispatched like usually.

In my .env file redis is set to be used for queue connection as well as cache driver:

QUEUE_CONNECTION=redis
CACHE_DRIVER=redis

I have two queue workers running, which compete for jobs from queue.

To push jobs there's console command:

class TestUnique extends Command
{
    protected $signature = 'test:unique';
    protected $description = 'Command description';

    private Dispatcher $dispatcher;

    public function __construct(Dispatcher $dispatcher)
    {
        parent::__construct();
        $this->dispatcher = $dispatcher;
    }

    public function handle()
    {
        $this->dispatcher->dispatch(new SomeJob(1));
        $this->dispatcher->dispatch(new SomeJob(2));
        $this->dispatcher->dispatch(new SomeJob(3));
        $this->dispatcher->dispatch(new SomeJob(4));
        $this->dispatcher->dispatch(new SomeJob(5));

        return 0;
    }
}

Job class looks like this (note that uniqueId is the same):

final class SomeJob implements ShouldQueue, ShouldBeUnique
{
    public function __construct(private int $id) { }

    public function handle(): void
    {
        var_dump("start handle $this->id");
        sleep(5);
        var_dump("finish handle $this->id");
    }

    public $uniqueFor = 3600;

    public function uniqueId()
    {
        return 1;
    }
}

Once we run console command to dispatch jobs, all of them are dispatched like usually without ShouldBeUnique. Logs:

queue_worker_2       | [2021-10-04 08:07:44][p0j7QmQt7JNFEWUoxdaEOuheJiPFTYrh] Processing: App\Console\Commands\SomeJob
queue_worker_2       | string(14) "start handle 1"
queue_worker_1       | [2021-10-04 08:07:44][DxFLi5V1UC7HfzpDFMmwv6po3Mh7Weap] Processing: App\Console\Commands\SomeJob
queue_worker_1       | string(14) "start handle 2"
queue_worker_2       | string(15) "finish handle 1"
queue_worker_2       | [2021-10-04 08:07:49][p0j7QmQt7JNFEWUoxdaEOuheJiPFTYrh] Processed:  App\Console\Commands\SomeJob
queue_worker_1       | string(15) "finish handle 2"
queue_worker_1       | [2021-10-04 08:07:49][DxFLi5V1UC7HfzpDFMmwv6po3Mh7Weap] Processed:  App\Console\Commands\SomeJob
queue_worker_1       | [2021-10-04 08:07:49][6sZoEH3WMsCMxYAmupy5RezlQezaAYag] Processing: App\Console\Commands\SomeJob
queue_worker_1       | string(14) "start handle 3"
queue_worker_2       | [2021-10-04 08:07:49][jQQNCm6MrsyxkxSClDsBNIfQezQIfBV1] Processing: App\Console\Commands\SomeJob
queue_worker_2       | string(14) "start handle 4"
queue_worker_1       | string(15) "finish handle 3"
queue_worker_1       | [2021-10-04 08:07:54][6sZoEH3WMsCMxYAmupy5RezlQezaAYag] Processed:  App\Console\Commands\SomeJob
queue_worker_2       | string(15) "finish handle 4"
queue_worker_2       | [2021-10-04 08:07:54][jQQNCm6MrsyxkxSClDsBNIfQezQIfBV1] Processed:  App\Console\Commands\SomeJob
queue_worker_1       | [2021-10-04 08:07:54][iGt3kbZTqj6lrXgm0SFFcaqVjbQ5tUqs] Processing: App\Console\Commands\SomeJob
queue_worker_1       | string(14) "start handle 5"
queue_worker_1       | string(15) "finish handle 5"
queue_worker_1       | [2021-10-04 08:07:59][iGt3kbZTqj6lrXgm0SFFcaqVjbQ5tUqs] Processed:  App\Console\Commands\SomeJob

This is not matter of cached code, because service definition uses queue:listen:

queue_worker:
    image: ${PROJECT_NAME}_php
    restart: unless-stopped
    command: php artisan queue:listen
    working_dir: /var/www/
    volumes: *php-volumes
    environment: *php-env
    networks:
        - main_network
    depends_on:
        - php

Can anyone tell what is ShouldBeUnique is intended for and what is wrong with current code?

Carlock answered 4/10, 2021 at 8:10 Comment(7)
What cache driver are you using?Defeasible
use "php artisan queue:restart" and dispatch againPortrait
redis is cache driver, restart won't help as queue:listen is usedCarlock
since you are running in containers (I assume) does each container have its own redis service or is it shared?Defeasible
There's only one redis container, which is usedCarlock
What I found is that problem appears only when code uses \Illuminate\Contracts\Bus\Dispatcher to dispatch jobs. Therefore if I were using dispatch() function problem won't appear, however generally it is not recommended as it brings implicit dependency into code.Carlock
Yes, actually it uses PendingDispatch which will dispatch anything in __destruct method.Carlock

© 2022 - 2024 — McMap. All rights reserved.