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;