Wait the light to fall

第十天 - Minion Stands Alone

焉知非鱼

Minion 作业队列是一个非常有用的工具,但有时我需要将它用于非 Web 项目。那么,如何在不需要 Mojolicious Web 应用程序的情况下使用 Minion?

如果我没有足够大的工作需要 Beam::Minion 提供的任务组织,虽然 Minion 可以用作完全独立的库,但最简单的解决方案就是构建一个 Mojolicious 应用程序。幸运的是,一个 Mojolicious 应用程序可以只有2行:

use Mojolicious::Lite;
app->start;

现在,如果我从未运行过 web 守护进程,那么这绝不会是一个网站。那么,如果没有人使用网络浏览器访问它,这可以称为 Web 应用程序吗?🤔

Add Minion #

要使用 Minion,请将 Minion 插件添加到应用程序。对于这个例子,我将使用 SQLite Minion 后端,这样我就不需要运行单独的数据库进程,但如果你有一个接受远程连接的数据库,Minion 可以在多台机器上工作。

plugin Minion => {
    SQLite => 'sqlite:' . app->home->child('minion.db'),
};

加载 Minion 插件后,我的应用程序获得了一些新功能:

  • 我可以使用 minion.add_task 助手程序添加 Minion 任务(可运行的代码)
  • 我可以通过多种方式排队工作:
  • 我可以使用 minion worker 命令运行一个 Minion worker,它将执行任何排队的作业

Create a Task #

我将创建一个名为 check_url 的任务来检查下载 URL 所需的时间。 Time::HiRes 核心模块将为我提供高分辨率时间。

#!/usr/bin/env perl

use v5.28;
use Mojolicious::Lite;
use experimental qw( signatures );
use Time::HiRes qw( time );

plugin Minion => {
    SQLite => 'sqlite:' . app->home->child('minion.db'),
};

app->minion->add_task(
    check_url => sub( $job, $url ) {
        my $start = time;
        my $tx = $job->app->ua->head( $url );
        my $elapsed = time - $start;
        $job->app->log->info(
            sprintf 'Fetching %s took %.3f seconds', $url, $elapsed
        );
        # If there's an error loading the web page, fail the job
        if ( $tx->error ) {
            $job->app->log->error(
                sprintf 'Error loading URL (%s): %s (%s)',
                    $url, @{ $tx->error }{qw( code message )},
            );
            return $job->fail(
                sprintf '%s: %s', @{ $tx->error }{qw( code message )}
            );
        }
        $job->finish( $elapsed );
    },
);

app->start;

Enqueuing Jobs #

现在我有一个任务,我可以排队一些工作。我可以使用 minion job 命令添加作业:

$ perl myapp.pl minion job -e check_url -a '["http://mojolicious.org"]'

或者通过加载Minion并使用 enqueue 方法 从另一个 Perl 脚本内部:

#!/usr/bin/env perl
use Minion;
my $minion = Minion->new(
    SQLite => 'sqlite:minion.db', # The same database as the worker
);
$minion->enqueue(
    check_url => ['http://mojolicious.org'],
);

Running a Worker #

我已经排队了工作,但没有发生任何事情,直到我使用 minion worker 命令运行一个 worker 才会发生任何事情:

$ perl myapp.pl minion worker

一旦工人启动,它将立即开始处理我告诉它运行的工作。

就是这样!我在没有 Mojolicious Web 应用程序的情况下使用 Minion。查看 Minion 应用程序的源代码和 enqueue.pl 脚本