Код: Выделить всё
use App\Events\Tenant\WalletTopupSuccessful;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels;
class AdjustWalletBalance implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct(
/**
* The amount to add to wallet balance. Can be negative for deductions.
*/
public float $amount,
/**
* User who's wallet should be adjusted.
*/
public User $user,
)
{
$this->onQueue('wallets');
}
/**
* Execute the job.
*/
public function handle(): void
{
$process_id = mt_rand();
$wallet = $user->wallet;
\Log::debug("starting $process_id at " . now());
\Log::debug("adjusting wallet balance with amount: {$this->amount}");
\Log::debug("current balance for $process_id: {$wallet->balance}");
// Increasing the running time for the job to make it easier to have
// two simultaneous jobs running for the sake of this demonstration.
sleep(10);
$wallet->balance = $wallet->balance + $this->amount;
$wallet->save();
\Log::debug("$process_id updated balance to {$wallet->balance}");
}
public function middleware()
{
return [(new WithoutOverlapping($this->user->id))];
}
}
У меня есть такая запись маршрута:
Код: Выделить всё
Route::get('/queue-test', function() {
dispatch(new \App\Jobs\Tenant\AdjustWalletBalance(50, User::first());
});

. И когда я проверяю свои файлы журналов, чтобы дополнительно проверить последовательность выполнения заданий, я вижу это:
Код: Выделить всё
[2023-09-24 19:12:42] local.DEBUG: starting 1007152283 at: 2023-09-24 19:12:42
[2023-09-24 19:12:42] local.DEBUG: adjusting wallet balance with amount: 50
[2023-09-24 19:12:42] local.DEBUG: current balance for 1007152283: 0
[2023-09-24 19:12:43] local.DEBUG: starting 241490440 at: 2023-09-24 19:12:43
[2023-09-24 19:12:43] local.DEBUG: adjusting wallet balance with amount: 50
[2023-09-24 19:12:43] local.DEBUG: current balance for 241490440: 0
[2023-09-24 19:12:52] local.DEBUG: 1007152283 updated balance to 50
[2023-09-24 19:12:53] local.DEBUG: 241490440 updated balance to 50
Я уже установил CACHE_DRIVER в массив, поэтому я не думаю, что это проблема с конфигурацией.
Я также пробовал использовать контракт MustBeUnique и устанавливать идентификатор пользователя как уникальный идентификатор, например
Код: Выделить всё
class AdjustWalletBalance implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(/**/)
{ /* Code */ }
public function uniqueId(): int
{
return $this->user->id;
}
public function handle()
{ /* Code */ }
}
Если я убью другого работника очереди и оставлю работать только одного, то последующие экземпляры задания добавляются в очередь, и кошелек пользователя корректно обновляется. Но у приложения будет несколько сотен пользователей, и мне нужно, чтобы несколько обработчиков очереди работали одновременно, чтобы быстро обрабатывать обновления их кошелька, поэтому один обработчик очереди не является вариантом.
Подробнее здесь: https://stackoverflow.com/questions/771 ... in-laravel
Мобильная версия