是否可以使用Attribute :: Handlers来实现重试逻辑

时间:2012-01-20 14:10:27

标签: perl

使用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多个潜艇。以这种方式做是一种好习惯,还是我能做什么简单的事?

您的帮助将受到高度赞赏。

1 个答案:

答案 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 = @_;
    ...
};

原型(@)帮助子作为运算符,不必总是用括号调用。

但是,无论如何,如果您喜欢方法属性并且它可以正常运行而且您可以让它不要咬你,使用它们。但你没必要。你应该读一下这些警告。