laravel — PHP-функция ограничения скорости

У меня есть функция PHP, которая вызывается, когда кто-то посещает POST www.example.com/webhook, Тем не менее, внешний сервис, который я не могу контролировать, иногда вызывает этот URL-адрес дважды подряд, нарушая мою логику, поскольку веб-крючок сохраняет данные в базе данных, для завершения которых требуется несколько мс.

Другими словами, когда поступает второй запрос (который нельзя игнорировать), первый запрос, вероятно, еще не завершен, однако мне нужно, чтобы он был выполнен в том порядке, в котором он поступил.

Итак, я создал небольшой хак в Laravel, который должен «задушить» выполнение с 5 секундами между ними. Кажется, работает большую часть времени. Однако ошибка в моем коде или какой-то другой недосмотр не позволяет этому решению работать каждый раз.

function myWebhook() {
// Check if cache value (defaults to 0) and compare with current time.
while(Cache::get('g2a_webhook_timestamp', 0) + 5 > Carbon::now()->timestamp) {
// Postpone execution.
sleep(1);
}
// Create a cache value (file storage) that stores the current
Cache::put('g2a_webhook_timestamp', Carbon::now()->timestamp, 1);
// Execute rest of code ...
}

Кто-нибудь, возможно, получил водонепроницаемое решение для этой проблемы?

0

Решение

По сути, вы разработали свою собственную упрощенную систему очередей, которая является правильным подходом, но вы можете использовать собственную очередь Laravel, чтобы иметь более надежное решение вашей проблемы.

  1. Определите работу, например: ProcessWebhook
  2. Когда запрос POST получен /webhook поставить работу в очередь

Работник очереди laravel будет обрабатывать по одному заданию за раз [1] в порядке их получения, гарантируя, что независимо от того, сколько запросов получено, они будут обрабатываться по одному и по порядку.

Реализация этого будет выглядеть примерно так:

  1. Создать новую работу, например: php artisan make:job ProcessWebhook
  2. Переместите ваш код обработки webhook в handle метод работы, например:

    public function __construct($data)
    {
    $this->data = $data;
    }
    
    public function handle()
    {
    Model::where('x', 'y')->update([
    'field' => $this->data->newValue
    ]);
    }
    
  3. Измените ваш контроллер Webhook для отправки нового задания при получении запроса POST, например:

    public function webhook(Request $request)
    {
    $data = $request->getContent();
    ProcessWebhook::dispatch($data);
    }
    
  4. Начните свою очередь работника, php artisan queue:work, которые будут выполняться в заданиях фоновой обработки в порядке их поступления, по одному за раз.

Вот и все, удобное решение для обработки веб-хуков по порядку, один за другим. Вы можете прочитать Документация очереди чтобы узнать больше о доступных функциях, включая повторение неудачных заданий, которые могут быть очень полезны.

[1] Laravel будет обрабатывать одну работу за раз на одного работника. Вы можете добавить больше работников, чтобы повысить пропускную способность очереди для других случаев использования, но в этой ситуации вам просто нужно использовать одного работника.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]