awohld has asked for the wisdom of the Perl Monks concerning the following question:

I have a subroutine that gets a web page using LWP::UserAgent. If the page returns an error I sleep for 100 seconds and try again.

Right now I use REDO in a named block to submit the page again, and I believe this might be looked upon as a poor implementation. What would be a better way to do this?

Here is my solution:
sub get_html { my %form; my $page; # Get ID ( $form{id}, $page ) = @_; my $data; get_page: { # Get web page my $response = $ua->post( $page, \%form ); # Check for errors if ($response->is_success) { $data = $response->content; } else { sleep 100; redo get_page; } } return \$data; }

Replies are listed 'Best First'.
Re: Using REDO in Subroutine, need better way?
by GrandFather (Saint) on Oct 09, 2006 at 03:35 UTC

    I'd be inclined to loop "for ever":

    while (1) { # Get web page my $response = $ua->post( $page, \%form ); # Check for errors if ($response->is_success) { $data = $response->content; return \$data; } sleep 100; }

    That is then easy to turn into a loop for some maximum number of times with error handling by falling out the bottom of the loop.


    DWIM is Perl's answer to Gödel
      Here is what I ended up with, I error out after 3 hours and send out an alert to my email if it fails.
      my $terminal_failure = 0; while (1) { # Get page my $response = $ua->post( $page, \%form ); if ($response->is_success) { $data = $response->content; last; } sleep 100; $terminal_failure++; # Die if no data for 3 hours send email alert. if ( $terminal_failure == 108 ) { my $failure = $response->status_line; my $msg = MIME::Lite->new( From =>'me@alerter.com', To =>'my@email.com Subject =>"", Data => "HTML download fail: $failure" ); $msg->send; die $failure; } }
Re: Using REDO in Subroutine, need better way?
by sgifford (Prior) on Oct 09, 2006 at 03:59 UTC
    The more traditional way to do something like this would be:
    my $data; do { # Get web page my $response = $ua->post( $page, \%form ); # Check for errors if ($response->is_success) { $data = $response->content; } else { sleep 100; } } until (defined($data));

    But I don't think that has much real advantage over your code or GrandFather's. Historical abuse of goto has caused a sort of disdain for anything resembling it, but in this case it's as clear as anything else.

Re: Using REDO in Subroutine, need better way?
by shmem (Chancellor) on Oct 09, 2006 at 06:00 UTC
    A block with redo is fine, named or not. It's just a style question - TIMTOWTDI.
    while(1) { ... } # why while? 1 never can get false for(;;) { ... } # just for nothing? do { ... } until $cond; # bad practice as per PBP? { ... redo unless $cond } # (fill in your complaint :-) uh-oh. "unless +"!

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}