(Laravel 5)监视队列(可选)并取消队列上的“已运行”作业

时间:2019-07-02 22:16:22

标签: queue laravel-5.8

我需要具备监视能力并能够取消队列中的“已运行”作业。

关于删除排队作业,有很多答案,但对于已经运行的作业却不是。

这种情况:我有一个“作业”,它由数据库中的数百行组成,需要针对Web服务一个一查询。

需要拾取每一行,针对Web服务进行查询,存储响应并更新其状态。

我已经以命令的形式工作(从/输出到控制台启动),但是现在我需要实现队列,以便允许更多用户堆积更多的作业。

到目前为止,我已经看到了Horizo​​n(由于缺少过程控制库,因此无法在Windows上运行)。但是,在周围看到的一些演示中,我缺少(我相信)一些需要的东西:

  • 动态可配置的超时(整个作业可能需要12个小时以上,具体取决于要处理选定作业的行数)
  • 取消已运行作业的能力。

我还考虑了将EACH REQUEST生成为新作业的选项,而不是在整个行集合中都看到“作业”(这将克服超时问题),但是这会给我一个Horizo​​n“待处理作业”列表每个作业成千上万的记录,这会杀死浏览器(我知道Redis可以完全不发痒地处理)。此外,我想不可能取消“所有属于X标签的作业”。

我一直在考虑打一个API路由,解雇工作并将其与应用程序分离,但是我发现这需要分叉过程。

为了具有取消功能,我将使用job_id实现数据库,并且当用户点击API取消作业时,我会将其标记为“已暂停”。在每个循环中,我都会检查其状态,如果发现“停止”,则将其杀死。

如果我错过了任何一个方面,我会补充或澄清一下。

由于我是Laravel的新手,所以我在这里寻求建议:我怎么能做到这一点?

2 个答案:

答案 0 :(得分:0)

Laravel队列具有3个重要的配置:

1. retry_after
2. timeout
3. tries

查看更多:https://laravel.com/docs/5.8/queues

  

动态可配置的超时(整个作业可能需要超过12个   小时,具体取决于所选作业要处理的行数)

我认为您可以在大约24小时后配置超时+ retry _。

  

可以取消已经运行的作业。

  • 在作业表中删除作业
  • 通过服务器中的进程ID删除进程

希望它对您有所帮助:)

答案 1 :(得分:0)

所以我终于想出了这个(有点笨拙)的解决方案:

在控制器中:

 public function cancelJob()
    {
        $jobs = DB::table('jobs')->get();

        # I could use a specific ID and user owner filter, etc.
        foreach ($jobs as $job) {
            DB::table('jobs')->delete($job->id);
        }

        # This is a file that... well, it's self explaining
        touch(base_path(config('afip_client.files.halt_process_signal')));

        return "Job cancelled - It will stop soon";
    }

在工作类别中(在model::chunk()函数内部)

                # CHECK FOR HALT SIGNAL AND [OPTIONALLY] STOP THE PROCESS
                if ($this->service->shouldHaltProcess()) {

                    # build stats, do some cleanup, log, etc...

                    $this->halted = true;
                    $this->service->stopProcess();

                    # This FALSE is what it makes the chunk() method to stop looping
                    return false;
                }

在服务舱中:

    /**
     * Checks the existence of the 'Halt Process Signal' file
     *
     * @return bool
     */
    public function shouldHaltProcess() :bool
    {
        return file_exists($this->config['files.halt_process_signal']);
    }


    /**
     * Stop the batch process
     *
     * @return void
     */
    public function stopProcess() :void
    {
        logger()->info("=== HALT PROCESS SIGNAL FOUND - STOPPING THE PROCESS ===");
        $this->deleteHaltProcessSignalFile();

        return ;
    }

它看起来不太优雅,但可以。 我已经浏览了整个网络,很多人都选择了Horizo​​n或其他不适合我的情况的工具。 如果有人有更好的方法来实现这一目标,欢迎分享。