2013/12/07

Futures advent day 7

Day 7 - Failures with Values

Yesterday we saw how we can use an else block to catch an exception and make it return a different value, including a success. Of course, it was a rather blunt way to handle a failure because it just turned any failure into a 599 HTTP status.

This is perhaps a good time to explain that, like done can be passed a list of multiple values for on_done and then to receive, so too can fail. The first value in this list must be true and ought to be well-behaved as a string, because get will use it as the exception it will die() with if it has to. Any other values in the list are ignored by get, but are passed in to on_fail and else.

Lets now make a better version of GET_checked that passes the failing HTTP response along with the failure.

sub GET_checked
{
  my ( $url ) = @_;

  GET( $url )->then( sub {
    my ( $r ) = @_;
    if( $r->code !~ m/^[23]../ ) {
      return Future->new->fail( $r->code." ".$r->message, $r );
    }
    else {
      return Future->new->done( $r );
    }
  });
}

We can now handle our errors better by only masking one kind of error that we are interested in.

my $f = GET_checked("http://my-site-here.com/a-page")
  ->else( sub {
     my ( $failure, $response ) = @_;

     if( $response->code != 500 ) {
       return Future->new->fail( $failure, $response );
     }

     return Future->new->done(
       HTTP::Response->new( 200, "OK", [],
         "Server is down, but have some fluffy kittens instead")
     );
  });

my $response = $f->get;

Now if the server fails with a 500 error, we will think of fluffy kittens instead. But any other error is still reported as a real failure.

<< First | < Prev | Next >

No comments:

Post a Comment