dragam0217
2017-10-25 22:28
浏览 371
已采纳

发送响应但保持长时间运行的脚本以防止超时?

I am wondering how to deal with this. I have a webhook endpoint which responds to a webhook call from Github.

It starts a long running process in where it clones the repository from which the webhook call was made.

/**
* The webhook endpoint.
*
* @param Request $request
* @return mixed
* @throws \Exception
*/
public function webhook(Request $request)
{
    // The type of GitHub event that we receive.
    $event = $request->header('X-GitHub-Event');

    $url = $this->createCloneUrl();
    $this->cloneGitRepo($url);

    return new Response('Webhook received succesfully', 200);
}

The problem with this is that Github gives an error when the response is not provided soon enough.

We couldn’t deliver this payload: Service Timeout

This is rightfully so because my cloneGitRepo method is simply blocking the execution of the response and it is taking too long.

How can I still deliver a response to acknowledge to Github that the webhook call has been made successfully and start my long running process?

I am using Laravel for all of this with Redis, maybe something can be accomplished there? I am open to all suggestions.

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongshang6790 2017-10-26 17:03
    已采纳

    What you're looking for is a queued job. Laravel makes this very easy with Laravel Queues.

    With queues, you setup a queue driver (database, redis, Amazon SQS, etc), and then you have one to many queue workers that are continuously running. When you put a job on the queue from your webhook method, it will be picked up by one of your queue workers and run in a separate process. The act of dispatching a queued job to a queue is very quick, though, so your webhook method will return quickly while the real work is being done by the queue worker.

    The linked documentation has all the details, but the general process will be:

    1. Setup a queue connection. You mention you're already using redis, I would start with that.

    2. Use php artisan make:job CloneGitRepo to create a CloneGitRepo job class.

      • It should implement the Illuminate\Contracts\Queue\ShouldQueue interface so that Laravel knows to send this job to a queue when it is dispatched.

      • Make sure to define properties on the class for any data you pass into the constructor. This is necessary so the worker can rebuild the job correctly when it is pulled off the queue.

      • The queue worker will call the handle() method to process the job. Any dependencies can be type hinted here and they will be injected from the IoC container.

    3. To dispatch the job to the queue, you can either use the global dispatch() helper function, or call the static dispatch() method on the job itself.

      • dispatch(new CloneGitRepo($url));

      • CloneGitRepo::dispatch($url);

    So, your webhook would look like:

    public function webhook(Request $request)
    {
        // The type of GitHub event that we receive.
        $event = $request->header('X-GitHub-Event');
    
        $url = $this->createCloneUrl();
    
        CloneGitRepo::dispatch($url);
    
        return new Response('Webhook received succesfully', 200);
    }
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题