Здравствуйте, я столкнулся с проблемой выполнения запроса, который отправляется одновременно два раза, но при этом изменяются данные у каждого из запросов.
Laravel обрабатывает их мгновенно и одновременно, как с этим быть?
Это ошибка не даёт покоя, поскольку баланс должен обновится при каждом запросе, очень много времени потратил на изучение этой проблемы, запускал и использовал queue от Laravel, но безрезультатно.
Что я могу предоставить, чтобы можно было решить проблему? Буду очень благодарен каждому.
Более подробнее об проблеме:
https://pastebin.com/taPmpiuE (pastebin) или:
Из модели User.php:
public function updateBalance($cash): void
{
$this->balance = $cash;
logger('Запрос отправлен, баланс: ' . $cash);
$this->save();
logger('Запрос сохранён, баланс: ' . $this->balance);
}
Из Controller.php:
public function buy_bet_withdraw(Request $request) {
$bet_amount = $request->get('bet');
$user = $request->user();
$bet_index = 1;
try {
$lockKey = 'lox_test_lock_' . $user->user_id;
if ($this->redis->setnx($lockKey, 1)) {
DB::transaction(function () use ($user, $bet_index, $bet_amount, $lockKey) {
$demo_balance = $user->demo_balance;
BuyLogs::insert([
'user_id' => $user->user_id,
'price' => floatval($bet_amount),
]);
$this->redis->publish('buy', json_encode([
'type' => 'cash',
'price' => 0
]));
$old_price = $user->balance;
$price = $user->balance - $bet_amount;
$user->updateBalance($price);
logger('Баланс пользователя: ' . $old_price . ', стал: ' . $price . ' | Слот: ' . $bet_index);
});
$this->redis->del($lockKey);
return response()->json([
'balance' => $user->balance,
]);
} else {
return response()->json(['success' => false, 'message' => 'Ошибка при обработке. Попробуйте позже.'], 400);
}
}
catch (\Throwable $error) {
\Log::error('Error: ' . $error->getMessage());
$this->redis->del($lockKey);
return response()->json(['success' => false, 'message' => 'Неизвестная ошибка'], 400);
}
}
Выполняю запрос:
const { data } = await axios.post('/api/buy', params);
Он находится в функции, которая выполняется два раза одновременно, тем самым отправляя два /api/buy, в первый раз баланс изменяется, но уже во второй он не меняется, но при этом возвращая успех об изменении баланса :(
Судя по логам:
[2023-12-06 05:57:54] local.DEBUG: Запрос отправлен, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Запрос отправлен, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Запрос сохранён, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Баланс пользователя: 1437.10, стал: 1427.1 | Слот: 0
[2023-12-06 05:57:54] local.DEBUG: Запрос сохранён, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Баланс пользователя: 1437.10, стал: 1427.1 | Слот: 1
Но если логически, то правильная последовательно будет такой: (но это мне не светит)
[2023-12-06 05:57:54] local.DEBUG: Запрос отправлен, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Запрос сохранён, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Баланс пользователя: 1437.10, стал: 1427.1 | Слот: 0
[2023-12-06 05:57:54] local.DEBUG: Запрос отправлен, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Запрос сохранён, баланс: 1427.1
[2023-12-06 05:57:54] local.DEBUG: Баланс пользователя: 1437.10, стал: 1427.1 | Слот: 1
А так же видно, что в одной секунде как раз обрабатывается запрос, хотелось бы как-то иметь последовательность, я использовал её от Laravel Queue, но без результатно :(
Использовать блокировщик от Redis не вариант, поскольку он блокирует запрос, но это мне не нужно, использовал для ознакомления, дабы как-то найти решение проблемы.
Вот так вот, надеюсь каждый понял про мою проблему :(