Subject: | Feature: auto-reconnect/retry on timeout/error |
Date: | Tue, 4 Jan 2011 16:16:16 -0500 |
To: | bug-redis [...] rt.cpan.org |
From: | Brian Dunavant <brian [...] omniti.com> |
Problem: Redis is distributed with a timeout of 300 seconds in the
default config. For obvious reasons there are disadvantages of
turning that off. However, putting error handling to reconnect
everywhere in your system that you use redis is also a bit annoying.
Having redis handle attempting a reconnection automatically would make
this less painful as now I only have to deal with actual errors and
not that I timed out or we just had a simple internet hiccup.
Solution: Have a flag to let Redis handle attempting to reconnect
once if there is an issue by passing auto_reconnect_and_retry => 1 in
the constructor.
Code:
Replace sub new() with the following (moves connection into a private
function) :
sub new {
my $class = shift;
my $self = {@_};
$self->{debug} ||= $ENV{REDIS_DEBUG};
bless($self, $class);
$self->__connect() || die $!;
$self;
}
-------
Modify the following line in AUTOLOAD from:
my $result = <$sock> || die "can't read socket: $!";
To:
my $result = <$sock> || $self->__reconnect_and_retry($send) || die
"can't read socket: $!";
--------
Add the following two functions:
sub __connect {
my $self = shift;
warn ">> Attempting to connect",$/ if $self->{debug};
$self->{sock} = IO::Socket::INET->new(
PeerAddr => $self->{server} || $ENV{REDIS_SERVER} ||
'127.0.0.1:6379',
Proto => 'tcp',
);
$self->{sock};
}
sub __reconnect_and_retry {
my ($self,$send) = @_;
return undef unless $self->{auto_reconnect_and_retry};
warn ">> Attempting to Reconnect",$/ if $self->{debug};
$self->__connect() || die "While trying to reconnect: $!";
warn ">> Attempting to Resend command: $send",$/ if $self->{debug};
my $sock = $self->{sock};
print $sock $send;
warn "<< Attempting to reread result",$/ if $self->{debug};
my $result = <$sock> || die "can't read socket: $!";
warn "<< Returning refetched result",$/ if $self->{debug};
return $result;
}
=========
After the fix (which is in my BrianRedis.pm module) assuming you have
a key "blah" with value "0" the following should now work.
; perl -I/home/brian -MBrianRedis -e '$r = BrianRedis->new(
autoreconnect => 1, debug => 1 ); sleep 400; print
"".$r->get("blah")."\n";'
Show quoted text
>> Attempting to connect
## get $VAR1 = 'blah';
Show quoted text>> GET blah
>> Attempting to Reconnect
>> Attempting to connect
>> Attempting to Resend command: GET blah
<< Attempting to reread result
<< Returning refetched result
<< $1
<< $VAR1 = '0';
0