使用Attribute::Handlers
来实现重试逻辑
我有近50个子程序,如verifyXXXX
。我需要为所有这些子实现重试逻辑。我想写一个实际实现sub的重试逻辑。如果sub的返回值为false / undef,则它将再次重试。
subs,以便调用者不会知道重试逻辑,例如。
verify_am_i_doing_good()
or die('sorry you are not doing as expected.');
verify_am_i_fine()
or die ('sorry you are not find.');
: :
这些函数的实际实现在包中是这样的。
use Attribute::Handlers;
use constant RETRY_LIMIT => 4;
use constant RETRY_DELAY => 2;
sub verify_am_i_doing_good : __retry
{
return 1 if ($x == $y);
return;
}
sub __retry : ATTR(CODE) {
my ($pkg, $sym, $code) = @_;
my $name = *{ $sym }{NAME};
no warnings 'redefine';
*{ $sym } = sub
{
my $self = $_[0];
my $result;
logMsg (INFO, "Executing subroutine $name with retry limit " . RETRY_LIMIT);
for (my $retryCount = 1; $retryCount <= RETRY_LIMIT; $retryCount++)
{
logMsg (INFO, "Executing subroutine $name with retry count $retryCount");
my $result = $code->( @_ );
if ($result)
{
logMsg (INFO, "Expected result observed in retry count $retryCount");
return wantarray ? @$result : $result;
}
else
{
logMsg (INFO, "Expected result is NOT observed in retry count $retryCount");
logMsg (INFO, "Retrying again by updating uixml");
sleep RETRY_DELAY;
$self->updateState();
}
}
logMsg (WARN, "Failed to verify expected result for subroutine $name with retry limit " . RETRY_LIMIT);
return;
};
}
在Attribute :: Attempts中使用Attribute :: Handlers的原因是,在失败的情况下,我需要在重试(重新执行)子例程之前调用另一个子例程updateState()
。
我从后面的帖子http://www.perl.com/pub/2007/04/12/lightning-four.html
中得到了编写重试逻辑的想法我主要担心的是,因为我使用这个__retry属性来接近50多个潜艇。以这种方式做是一种好习惯,还是我能做什么简单的事?
您的帮助将受到高度赞赏。
答案 0 :(得分:2)
您不需要属性来执行子包装。在Memoize
(或Memoize::Attrs
之前)已经Attribute::Memoize
了很长时间。您可以查看Memoize
如何处理它。
最近,我正在为另一个接口调用的函数编写一些Perl。从这个接口传递给Perl函数的所有参数都将以我的部门使用的时髦但通用的格式传递。我没有在任何地方处理这个问题,而是编写了一个像这样的逻辑包装器
sub external (@) {
my ( $subname, $code ) = @_;
...
my $wrapped
= sub {
my $count = 5;
while ( --$count and not my @results = &$code ) {
adjust_stuff();
}
return @results;
};
{ no strict 'refs'; # my special "no-block"
*$subname = $wrapped;
}
return;
}
并且像这样使用它(有些人不喜欢使用“胖逗号”)
external something_I_want_to_do => sub {
my @regular_old_perl_args = @_;
...
};
原型(@)
帮助子作为运算符,不必总是用括号调用。
但是,无论如何,如果您喜欢方法属性并且它可以正常运行而且您可以让它不要咬你,使用它们。但你没必要。你应该读一下这些警告。