AnyEvent-Retry

 view release on metacpan or  search on metacpan

lib/AnyEvent/Retry.pm  view on Meta::CPAN

sub set_timer {
    my ($self, $time, $i) = @_;
    return $self->handle_tick($i) if $time <= 0;

    weaken $self;
    $self->_set_timer(
        AnyEvent->timer( after => $time, cb => sub {
            $self->kill_timer;
            $self->handle_tick($i);
        }),
    );

    return;
}

# called when the timer ticks; start the user's code running
sub handle_tick {
    my ($self, $this_i) = @_;
    $self->run_code;
}

# called when the user's code signals success or error
sub handle_result {
    my ($self, $success, $status, $msg) = @_;

    # if we hit these two cases, we are done forever
    if($success){
        $self->_sent_result(1);
        $self->on_success->($msg);
        return;
    }
    elsif($status =~ /error/){
        $self->_sent_result(1);
        $self->on_failure->( exception => $msg, $status );
        return;
    }

    # no error, but not success (try again later)
    my ($next_time, $next_i) = $self->interval->next;
    if($self->max_tries > 0 && $next_i > $self->max_tries){
        # done forever
        $self->_sent_result(1);
        $self->on_failure->( max_tries => $self->max_tries );
        return;
    }

    # we didn't get the result this time, and we haven't exceeded
    # $max_tries, so set the timer and do the whole thing again
    $self->set_timer( $next_time, $next_i );
    return;
}

# start the user's code running, with a continuation-passing-style
# callback to call when the result is ready
sub run_code {
    my ($self) = @_;

    # we weaken $self here so that if the user does "undef $retry", we
    # DEMOLISH the object and silently discard the results of the
    # running code.  feel free to subclass if want to keep the class
    # alive arbitrarily.
    weaken $self;

    my $success = sub {
        my $result = shift;
        return unless defined $self;
        $self->handle_result(($result ? 1 : 0), 'success', $result);
        return;
    };

    my $error = sub {
        my $msg = shift;
        return unless defined $self;
        $self->handle_result(0, 'run error', $msg);
        return;
    };

    try   { $self->try->($success, $error) }
    catch { $self->handle_result(0, 'startup error', $_) };
    return;
}

# if the timer is running, stop it until resume is called
sub pause {
    my $self = shift;
    $self->kill_timer;
}

# fake a timer tick; run the user code, and set the timer to retry if
# necessary
sub resume {
    my $self = shift;
    $self->kill_timer; # just in case
    $self->handle_tick(0);
}

# start the process.  if the timer is running, die.  if the timer is
# not running, start completely over.
sub start {
    my $self = shift;
    confess 'the job is already running' if $self->has_timer;

    $self->interval->reset;
    $self->_sent_result(0);
    $self->set_timer( $self->after, 0 );
    return;
}

__PACKAGE__->meta->make_immutable;



=pod

=head1 NAME

AnyEvent::Retry - try something until it works

=head1 VERSION

version 0.03



( run in 1.531 second using v1.01-cache-2.11-cpan-df04353d9ac )