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

时间:2017-10-25 22:28:25

标签: php laravel laravel-5 github-api webhooks

我想知道如何处理这件事。我有一个webhook端点,它响应来自Github的webhook调用。

它启动一个长时间运行的进程,它克隆从中进行webhook调用的存储库。

  [Table("Agency")]
  public class Agency
  {
    [Key]
    public int AgencyId { get; set; }
    [ForeignKey("Users")]
    public int UserId { get; set; }

    public string AgencyName { get; set; }

    public string Address { get; set; }

    public string City { get; set; }

    public string Description { get; set; }

    public DateTime CreatedDate { get; set; }
    [Required]
    public virtual Users Users { get; set; }//Foriegn key
}

问题在于,如果没有尽快提供响应,Github就会出错。

  

我们无法提供此有效负载:服务超时

这是理所当然的,因为我的/** * 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); } 方法只是阻止了响应的执行,而且花费的时间太长了。

我怎样才能提交回复以确认Github已成功完成webhook通话并开始我的长时间运行过程?

我正在使用Laravel与Redis一起使用,也许可以在那里完成一些事情?我对所有建议持开放态度。

1 个答案:

答案 0 :(得分:2)

您正在寻找的是排队的工作。 Laravel使用Laravel Queues非常容易。

使用队列,您可以设置队列驱动程序(数据库,redis,Amazon SQS等),然后您有一个到多个连续运行的队列工作程序。当您从webhook方法将作业放入队列时,它将由您的一个队列工作程序选取并在单独的进程中运行。但是,将排队作业分派到队列的行为非常快,因此在队列工作人员完成实际工作时,webhook方法将快速返回。

链接文档包含所有详细信息,但一般过程如下:

  1. 设置队列连接。你提到你已经在使用redis,我会从那开始。

  2. 使用php artisan make:job CloneGitRepo创建CloneGitRepo作业类。

    • 它应该实现Illuminate\Contracts\Queue\ShouldQueue接口,以便Laravel知道在调度时将此作业发送到队列。

    • 确保为传递给构造函数的任何数据定义类的属性。这是必要的,因此当工作人员从队列中取出时,工作人员可以正确地重建工作。

    • 队列工作程序将调用handle()方法来处理作业。任何依赖项都可以在此处进行类型提示,它们将从IoC容器中注入。

  3. 要将作业分派到队列,您可以使用全局dispatch()辅助函数,也可以在作业本身上调用静态dispatch()方法。

    • dispatch(new CloneGitRepo($url));

    • CloneGitRepo::dispatch($url);

  4. 所以,你的webhook看起来像是:

    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);
    }