package Mojo::Redis::Sentinel;
use Mojo::Base 'Mojo::Redis';
use Scalar::Util 'weaken';
has service => 'mymaster';
has sentinels => sub { ['127.0.0.1:26379'] };
has sentinels_connection_timeout => 0.1;
has sentinels_inativity_timeout => 0.1;
sub sentinel {
my $self = shift;
$self->execute('sentinel' => \@_);
}
sub emit_or_warn {
my ($self, $ev, $msg) = @_;
$self->has_subscribers($ev) ?
$self->emit_safe($ev => $msg) : warn $msg;
}
sub connect {
my $self = shift;
say "SENTINEL CONNECT";
# Before connecting to a Redis server, we must first
# obtain its address from a sentinel.
$self->server(undef);
$self->find_master;
}
sub find_master {
my $self = shift;
my $sentinels = $self->sentinels;
$self->{tempo} = [];
for my $srv (@$sentinels) {
my $stnl = Mojo::Redis->new(server => $srv);
push @{$self->{tempo}}, $stnl;
$stnl->timeout($self->sentinels_connection_timeout);
$stnl->execute('sentinel' => 'get-master-addr-by-name', $self->service => sub {
# Do nothing if a server was already found
return if $self->server;
my ($stnl, $res) = @_;
my ($ip, $port) = @$res;
if (not $ip or $ip eq 'IDONTKNOW') {
$self->emit_or_warn(error => "sentinel ".$stnl->server.
"does not know any master server");
return;
}
$self->server("$ip:$port");
say "FOUND MASTER: ".$self->server;
$self->ioloop->timer(0 => sub { $self->SUPER::connect });
delete $self->{tempo};
});
}
}
sub DESTROY { say "SENTINEL DESTROY" }
1;