duanji1026 2018-01-28 23:00
浏览 84

限速PHP功能

I have a php function which gets called when someone visits POST www.example.com/webhook. However, the external service which I cannot control, sometimes calls this url twice in rapid succession, messing with my logic since the webhook persists stuff in the database which takes a few ms to complete.

In other words, when the second request comes in (which can not be ignored), the first request is likely not completed yet however I need this to be completed in the order it came in.

So I've created a little hack in Laravel which should "throttle" the execution with 5 seconds in between. It seems to work most of the time. However an error in my code or some other oversight, does not make this solution work everytime.

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 ...
}

Anyone perhaps got a watertight solution for this issue?

  • 写回答

1条回答 默认 最新

  • doushouj966020 2018-01-28 23:38
    关注

    You have essentially designed your own simplified queue system which is the right approach but you can make use of the native Laravel queue to have a more robust solution to your problem.

    1. Define a job, e.g: ProcessWebhook
    2. When a POST request is received to /webhook queue the job

    The laravel queue worker will process one job at a time[1] in the order they're received, ensuring that no matter how many requests are received, they'll be processed one by one and in order.

    The implementation of this would look something like this:

    1. Create a new Job, e.g: php artisan make:job ProcessWebhook
    2. Move your webhook processing code into the handle method of the job, e.g:

      public function __construct($data)
      {
          $this->data = $data;
      }
      
      public function handle()
      {
          Model::where('x', 'y')->update([
              'field' => $this->data->newValue
          ]);
      }
      
    3. Modify your Webhook controller to dispatch a new job when a POST request is received, e.g:

      public function webhook(Request $request)
      {
          $data = $request->getContent();
          ProcessWebhook::dispatch($data);
      }
      
    4. Start your queue worker, php artisan queue:work, which will run in the background processing jobs in the order they arrive, one at a time.

    That's it, a maintainable solution to processing webhooks in order, one-by-one. You can read the Queue documentation to find out more about the functionality available, including retrying failed jobs which can be very useful.

    [1] Laravel will process one job at a time per worker. You can add more workers to improve queue throughput for other use cases but in this situation you'd just want to use one worker.

    评论

报告相同问题?

悬赏问题

  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试,帮帮忙吧
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python