使用與Exception::Class結合Log::Any和Log::Any::Adapter讓你把所有的作品以最小的大驚小怪和最大的靈活性在一起:
#!/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;
}
輸出示例:
Job exceptional_job started
Processed 5 items
........................................
The worker spent too much time processing items
Spent 12 seconds. Limit is 10.
或
Job exceptional_job started
Processed 5 items
The worker was given too many items to process
195 items remain. Limit is 100.
感謝您的回答,第一種方法我是你現在唱歌,用exitcode路由(使用ReturnMessage作爲返回參數)。我會嘗試按照你的建議嘗試:Tiny/TryCatch。我必須小心,因爲多次調用WorkingProc。不要緊,以前呼叫乾淨或不乾淨。主程序決定是否有意義下一個循環,它依賴於退出代碼。 – Znik
我發現了另一個異常捕獲器:Try :: Tiny :: SmartCatch。 TryCatch很差,Try :: Tiny很有趣。我會用這個。但是,我發現非常新鮮的Try :: Tiny :: SmartCatch,在'try'塊中由'throw'生成的這個'catch'過濾器攔截棧名爲異常。非常好,類似於java :)你可以在這裏找到它:https://github.com/mysz/try-tiny-smartcatch – Znik
@znik可以安裝[Try :: Tiny :: SmartCatch] [來自CPAN]( https://開頭metacpan。組織/模塊/ TRY ::微型:: SmartCatch)。這比從github複製代碼更好。不過,我強烈建議你使用vanilla'Try :: Tiny':這是事實上的標準,它解決了所有傳統的錯誤處理方法'eval {...};如果($ @){...}'有。無論你最終使用什麼,我認爲你想使用適當的異常處理是很好的。 – amon