Mojo-Redis/t/connection-lost.t
use Mojo::Base -strict;
use Test::More;
use Mojo::Redis;
use Errno qw(ECONNREFUSED ENOTCONN);
# Dummy server
my $port = Mojo::IOLoop::Server->generate_port;
my $server_id = make_server(Mojo::IOLoop->singleton);
my $redis = Mojo::Redis->new("redis://localhost:$port");
my $err;
note 'Promises should be rejected on error';
my $db = $redis->db;
Mojo::IOLoop->next_tick(sub { $db->connection->disconnect });
get_p($db)->wait;
is $err, 'Premature connection close', 'client disconnected';
$err = '';
get_p($redis->db)->wait;
is $err, 'Premature connection close', 'server closed stream';
my $err_re = join '|', map { local $! = $_; quotemeta "$!" } ECONNREFUSED, ENOTCONN;
$err = '';
Mojo::IOLoop->remove($server_id);
get_p($redis->db)->wait;
{
local $TODO = $err =~ /$err_re/ ? '' : "server most likely disappeared ($@)";
like $err, qr/$err_re/, 'server disappeared';
}
note 'Do not reconnect in the middle of a transaction';
$server_id = make_server($redis->_blocking_connection->ioloop);
$db = $redis->db;
my $step = 0;
my @err;
for my $m (qw(multi incr incr exec)) {
eval { $db->$m($m eq 'incr' ? ($0) : ()); ++$step } or do { push @err, $@ };
note "($step) $@" if $@;
}
is $step, 1, 'all blocking methods fail after the first fail';
like shift(@err), qr{^$_}, "expected $_"
for 'Premature connection close', 'Redis server has gone away', 'Redis server has gone away';
isnt $redis->_blocking_connection, $db->connection(1), 'fresh connection next time';
is $redis->_blocking_connection->ioloop, $db->connection(1)->ioloop, 'same blocking ioloop';
note 'No blocking connection should be put back into connection queue';
$db = $redis->db;
$db->connection(1)->{stream} = 1; # pretend we are connected
undef $db;
ok !(grep { warn $_; $_->ioloop ne Mojo::IOLoop->singleton } @{$redis->{queue}}), 'no blocking connections in queue';
done_testing;
sub get_p {
return shift->get_p($0)->then(sub { diag "Should not be successfule: @_" })->catch(sub { $err = shift });
}
sub make_server {
return shift->server(
{port => $port},
sub {
my ($loop, $stream) = @_;
$stream->on(
read => sub {
my ($stream, $buf) = @_;
return $stream->write("+OK\r\n") if $buf =~ /EXEC/; # Should not come to this
return $stream->write("+OK\r\n") if $buf =~ /MULTI/;
return $stream->close;
}
);
}
);
}