Log::AnyとLog::Any::AdapterをException::Classと組み合わせて使用すると、最小限の手間と最大限の柔軟性ですべての要素をまとめることができます。
#!/usr/bin/env perl
package My::Worker;
use strict; use warnings;
use Const::Fast;
use Log::Any qw($log);
use Exception::Class (
JobException => { fields => [qw( exit_code )] },
TooManyItemsException => {
isa => 'JobException',
description => 'The worker was given too many items to process',
},
TimeExceededException => {
isa => 'JobException',
description => 'The worker spent too much time processing items',
},
);
sub work {
my $jobid = shift;
my $items = shift;
const my $ITEM_LIMIT => 100;
const my $TIME_LIMIT => 10;
$log->infof('Job %s started', $jobid);
shift @$items for 1 .. 5;
$log->info('Processed 5 items');
if (0.25 > rand) {
# throw this one with 25% probability
if (@$items > $ITEM_LIMIT) {
TooManyItemsException->throw(
error => sprintf(
'%d items remain. Limit is %d.',
scalar @$items, $ITEM_LIMIT,
),
exit_code => 5,
);
}
}
{ # simulate some work that might take more than 10 seconds
local $| = 1;
for (1 .. 40) {
sleep 1 if 0.3 > rand;
print '.';
}
print "\n";
}
my $time_spent = time - $^T;
($time_spent > $TIME_LIMIT) and
TimeExceededException->throw(
error => sprintf (
'Spent %d seconds. Limit is %d.',
$time_spent, $TIME_LIMIT,
),
exit_code => 6);
$log->info('All processed succesfully');
return;
}
package main;
use strict; use warnings;
use Log::Any qw( $log );
use Log::Any::Adapter ('Stderr');
eval { My::Worker::work(exceptional_job => [1 .. 200]) };
if (my $x = JobException->caught) {
$log->error($x->description);
$log->error($x->error);
exit $x->exit_code;
}
出力例:
ジョブ exception_job started
5 アイテムを処理しました
...................................................
ワーカーがアイテムの処理に時間をかけすぎた
12秒かかりました。制限は 10 です。
また
ジョブ exception_job started
5 アイテムを処理しました
ワーカーに与えられたアイテムが多すぎて処理できませんでした
残り195点。制限は 100 です。