我的 Perl 应用程序使用的资源有时会暂时不可用,从而导致使用die
. 最值得注意的是,它访问由多个线程共享的 SQLite 数据库,以及使用 through 与其他应用程序共享的 SQLite 数据库DBIx::Class
。每当发生此类异常时,都应重试该操作,直到达到超时为止。
我更喜欢简洁的代码,因此我很快就厌倦了为每个这样的操作重复输入 7 行额外的行:
use Time::HiRes 'sleep';
use Carp;
# [...]
for (0..150) {
sleep 0.1 if $_;
eval {
# database access
};
next if $@ =~ /database is locked/;
}
croak $@ if $@;
...所以我将它们放入(特定于数据库访问的)函数中:
sub _retry {
my ( $timeout, $func ) = @_;
for (0..$timeout*10) {
sleep 0.1 if $_;
eval { $func->(); };
next if $@ =~ /database is locked/;
}
croak $@ if $@;
}
我这样称呼:
my @thingies;
_retry 15, sub {
$schema->txn_do(
sub {
@thingies = $thingie_rs->search(
{ state => 0, job_id => $job->job_id },
{ rows => $self->{batchsize} } );
if (@thingies) {
for my $thingie (@thingies) {
$thingie->update( { state => 1 } );
}
}
} );
};
有没有更好的方法来实现这一点?我在重新发明轮子吗?我应该使用 CPAN 上的代码吗?