I have saas service which working with API. It has limits so I need that one user account doing only one request at the same time.
For this I queuing with OnQueue($user->name);
then in handle()
doing job…
I need only one job can be run in users queue. At the same time may be run only diffent queues 1 job per 1 queue.
Im using redis connection.
This my job class:
public function __construct(Accounts $acc)
{
$this->acc = $acc;
$this->ownjob = $acc->prepareJobQueue();
}
public function handle()
{
$acc = $this->acc;
$job = $this->ownjob;
$api = new Api([
'login' => $acc->login,
'password' => $acc->password,
]);
if ($api->checkLogin()) {
info("{$acc->login} OK Authorized");
foreach ($job['queue'] as $term) {
switch($term['type']) {
case 'hashtag':
info("{$acc->login} Queuing: type - {$term['type']}, value - {$term['value']}");
$hashtag = Hashtags::where('cha_name',$term['value'])->first();
$answer = $api->getUsersByHashtag($hashtag,50);
break;
case 'concurency':
info("{$acc->login} Queuing: type - {$term['type']}, value - {$term['value']}");
$soc_user = Users::where('soc_unique_id',$term['value'])->first();
$answer = $api->getUserFollowers($soc_user);
break;
default:
break;
}
}
} else {
info("{$acc->login} NOT Authorized - STOP JOB");
}
}
This is how I dispatching job:
$accounts = Accounts::select(['id', 'login', 'hashtag_filter', 'concurency_filter'])->whereNotNull('hashtag_filter')->get();
foreach ($accounts as $acc) {
doFollowing::dispatch($acc)->onQueue($acc->login);
}
3
Answers
You could limit
numprocs
per queue in your Supervisor or Horizon setup.If you only spawn one queue worker per user I believe you will get your desired behaviour.
Use mxl/laravel-queue-rate-limit Composer package.
It enables you to rate limit Laravel jobs on specific queue without using A third party driver such as
Redis
.Install it with:
This package is compatible with Laravel 5.5+ and uses [auto-discovery][1] feature to add
MichaelLedinLaravelQueueRateLimitQueueServiceProvider::class
to providers.Add rate limit (x number of jobs per y seconds) settings to
config/queue.php
:These settings allow to run 1 job every 5 seconds on
mail
queue.Make sure that default queue driver (
default
property inconfig/queue.php
) is set to any value exceptsync
.Run queue worker with
--queue mail
option:You can run worker on multiple queues, but only queues referenced in
rateLimit
setting will be rate limited:Jobs on
default
queue will be executed without rate limiting.Queue some jobs to test rate limiting:
You could use Laravel’s builtin rate limiting for this (note that it does require Redis).
Inside your job:
Note that if you don’t provide a second callback to then, it will throw an exception if it cannot obtain the lock (which will cause your job to fail)
If you’re using Laravel 6 or higher you could also opt to do this in a job middleware, rather than in the job itself (handy if you have multiple jobs that share the same lock)
More info on Laravel’s rate limiting: https://laravel.com/docs/5.8/queues#rate-limiting