(Laravel 5) 监控并可选择取消队列中已经 运行 的作业

(Laravel 5) Monitor and optionally cancel an ALREADY RUNNING job on queue

我需要实现监视和取消队列中已经 运行 作业的能力。

有很多关于删除 QUEUED 作业的答案,但没有关于已经 运行 的答案。

情况是这样的:我有一个 "job",它由数据库中的数百行组成,需要针对 Web 服务逐一查询。

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

我已经将其用作命令(从控制台启动/输出到控制台),但现在我需要实施队列以允许从更多用户那里堆积更多作业。

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

我还考虑了将 EACH REQUEST 生成为新作业的选项,而不是将 "job" 视为整个行集合(这将克服超时问题),但这会给我一个 Horizo​​n "pending jobs" 每个作业包含数十万条记录的列表,这会杀死浏览器(我知道 Redis 可以毫不费力地处理这个问题)。此外,我想取消 "all jobs belonging to X tag".

是不可能的

我一直在考虑点击 API 路线,解雇作业并将其与应用程序分离,但我发现这需要分叉流程。

为了能够取消,我会用 job_id 实现一个数据库,当用户点击 API 取消作业时,我会将其标记为 "halted" .在每个循环中,我都会检查它的状态,如果它找到 "halted" 然后自杀。

如果我遗漏了任何方面,请大声疾呼,我会添加或澄清。

所以我在这里寻求建议,因为我是 Laravel 的新手:我怎样才能做到这一点?

Laravel 队列有 3 个重要配置:

1. retry_after
2. timeout
3. tries

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

Dynamically configurable timeout (the whole job may take more than 12 hours, depending on the number of rows to process on the selected job)

我想你可以配置超时 + retry_after 大约 24 小时。

Ability to CANCEL an ALREADY RUNNING job.

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

希望对你有帮助:)

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

在控制器中:

 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('files.halt_process_signal')));

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

工作中 class(在 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;
                }

服役中class:

    /**
     * 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 或其他不适合我的工具。 如果谁有更好的实现方式,欢迎分享。