mxl/laravel-queue-rate-limit

Worker exits when used with --stop-when-empty flag

Opened this issue · 1 comments

First of all, thank you for this nice package which is one of its kind when it comes to rate limiting without Redis.

I am not sure whether this is really an issue which can be solved by this package of not. But I want to log this information (even if you prefer to close it as out of scope) here as it will be helpful for other users of the package.

So, I am using worker in a mode where it exits when queue is empty. Like mentioned in laravel doc here https://laravel.com/docs/7.x/queues#running-the-queue-worker

php artisan queue:work --stop-when-empty

Now, let's say we have 10 items in the mail queue and mail queue is rate limited like this :

'rateLimits' => [
     'mail' => [ // queue name
        'allows' => 1, // 1 job
        'every' => 5 // per 5 seconds
     ]
]

Now as soon as worker processes the first job & first job got complete within 2 seconds. Now, we have 9 jobs pending but just because of rate limit, none of job can be picked up within 5 seconds. This sends worker a signal that queue is empty and worker get terminated! Ideally, queue is yet not empty and work should resume the queue after 5 seconds.

Now for those who are using this package along with worker invoked from laravel scheduler like this (I know it should be from supervisor instead, but let's say due to some limitations):

$schedule->command('queue:work --stop-when-empty --timeout=120 --tries=3')->everyMinute();

They will get an impression like rateLimiter is limiting to 1 minute instead of seconds.. This is because worker process get terminated & it get invoked after 1 minutes (or with interval you have set in scheduler). So, that gives you impression like something is wrong with package configuration where every parameter is in minutes instead of seconds :)

Possible work around for this is to set rate limits like this :

'rateLimits' => [
        'default' => [ // queue name
            'allows' => 12, // 12 job
            'every' => 60 // per 1 minute
        ]
    ]

Above will make worker to pick 12 jobs per minutes. However, know that this can result in burst of 12 jobs per few seconds which might or might not work for you based on your scenario. (If API supports leaky bucket, it will work. If API has strict only second based limits, it might not work for you)

I can confirm this, with using laravel 8 and queue connection's driver as database '--stop-when-empty' tag is not working. It just logs 'Next job will be started in x seconds' and then nothing happens.