【问题标题】:Is it ok to use Attribute::Handlers for implementing retry logic是否可以使用 Attribute::Handlers 来实现重试逻辑
【发布时间】:2012-01-20 14:10:26
【问题描述】:

使用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::Handlers 代替 Attribute::Attempts 的原因是,在失败的情况下,我需要在重试(重新执行)子例程之前调用另一个子例程 updateState()

我从http://www.perl.com/pub/2007/04/12/lightning-four.html下面的帖子中得到了编写重试逻辑的想法

我主要担心的是,因为我使用这个 __retry 属性来处理近 50 多个潜艇。这样做是一个好习惯还是有什么简单的我可以做的?

我们将非常感谢您的帮助。

【问题讨论】:

    标签: perl


    【解决方案1】:

    你不需要属性来做一个子包装器。 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 = @_;
        ...
    };
    

    原型(@) 帮助sub 充当运算符,并且不需要总是用括号调用。

    但无论如何,如果你喜欢方法属性并且它有效并且你可以让它不咬你,使用它们。但你不必。不过,您可能应该阅读注意事项。

    【讨论】:

    • @Zaid 请参阅此页面上的警告部分:perl.com/pub/2007/04/12/lightning-four.html。当然,人们用 Perl 用 AUTOLOAD 和其他东西做的很多事情并没有太大的机会。当有太多巫师在同一狭窄区域施法时,这只是 Perl 魔法的普遍问题。但是,增强和处理组合函数的函数又是函数式编程的主要内容。
    • @Zaid,哦,我忘记了一个想法。 “核心”属性是lvaluemethodlockedunique。两个已弃用,一个 lvalue 一直被列为“实验性”(无论如何我都不喜欢它的局限性)。我通常最后会感叹我想使用lvalue,但没有。哦,我在 perlmonks 上发现了这一点:“:unique 属性已被设为无操作,因为它当前的实现存在根本缺陷且不是线程安全的。”
    • @Axeman => 你可以用我写的metacpan.org/module/Lvalue 模块解决lvalue 属性的一些(但绝不是全部)怪癖。它旨在解决左值设置器遭受的封装违规问题。但是,它对提供列表上下文支持没有做任何事情,这必须在 C 级别进行修复。我同意这只是在问题上施展更多魔法,但有时魔法是可以的。
    猜你喜欢
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    相关资源
    最近更新 更多