首页 > 解决方案 > 在 Mojolicious/Minion::Job 上设置“完成”事件

问题描述

我试图让 Minion 作业在完成后反馈到 Mojolicious 网络应用程序(可能通过向 API 发布消息)。然后,这里的基本思想是让 Web 应用程序反馈给已上传/启动作业的客户端。

我试过这样做:

get '/' => sub {
    my $c = shift;
    my $id = $c->minion->enqueue('thing', [ qw/a b 1/, { foo => 'bar' } ]);

    my $job = $c->minion->job($id);

    $job->on(finish => sub ($job) {
              my $id   = $job->id;
              my $task = $job->task;
              $job->app->log->info(qq{Job "$id" was performed with task "$task"});
         });


    $c->render(template => 'index');
};

这不起作用 - 我猜是因为事件仅在执行作业的过程中发出,并且事件不会被序列化和排队。

如果我这样做:

app->minion->add_task
    (thing => sub ($job, $c, $sub, @args) {
     $job->on(finish => sub ($job) {
              my $id   = $job->id;
              my $task = $job->task;
              $job->app->log->info(qq{Job "$id" was performed with task "$task"});
          });
          sleep 2;
     });

它工作正常,但这意味着我必须为每个任务添加事件处理 - 这增加了代码的复杂性。

有没有办法避免这样做?

我在想:

  1. 能够为作业设置默认类(因此作业都是 Mojo::Job 的子类 - 例如Minion::Job::WithFeedback
  2. 更好的是,能够将角色注入到任务创建中(这样你就可以做到$c->minion->enqueue('thing', [ qw/a b 1/, { foo => 'bar' } ], { roles => qw/+WithFeedback +WithTimeout/);

我知道我可以定期轮询所有作业并查看状态发生了什么变化——这就是Minion::Admin插件所做的——但我想看看是否有一种不同的方式不需要轮询数据库。

这可能吗?当我们这样做的时候——这本身是一个坏主意吗?

标签: perlmojolicious

解决方案


推荐阅读