Gearman::Worker と Parallel::Prefork の組み合わせ

こちらを参考に。

use strict;
use warnings;
use Gearman::Worker;
use Parallel::Prefork;
use Storable qw( thaw );
use List::Util qw( sum );
use Perl6::Say;

sub MaxRequestsPerChild () { 60 }

my $pm = Parallel::Prefork->new({
    max_workers  => 3,
    trap_signals => {
        TERM => 'TERM',
        HUP  => 'TERM',
    },
});

my $worker = Gearman::Worker->new;
$worker->job_servers("localhost");
$worker->register_function(sum => sub { sum @{ thaw($_[0]->arg) } });

{
    $pm->start and last;

    say "spawn $$";
    my $reqs_before_exit = MaxRequestsPerChild;
    $SIG{TERM} = sub { $reqs_before_exit = 0 };

    sleep 1; # すぐに働くと、たまにちゃんとjob処理しないので。

    $worker->work(
        on_start => sub { --$reqs_before_exit },
        stop_if  => sub { ! $reqs_before_exit > 0 },
    );

    say "FINISHED $$";
    $pm->finish;
}

$pm->wait_all_children;

どうもこれ↓だとダメぽい。

while ( $reqs_before_exit > 0 ) {
    $worker->work(
        on_start => sub { --$reqs_before_exit }
    );
}

よく*1'$worker->work() while 1'とか見るけど、あれ意味ないような。workするだけで、中で無限ループってる気がする。

*1:podでも