def _connect(self, sock, addr, callback): self._reset() self._stream = DownStream(sock, io_loop=self._io_loop) self._stream.connect(addr, callback=callback, timeout=self.timeout) self._stream.read_until_close(self._on_close, self._on_read)
class SentinelClient(Client): def __init__(self, io_loop=None, disconnect_callback=None): super(SentinelClient, self).__init__(io_loop=io_loop) self._disconnect_callback = disconnect_callback def on_disconnect(self): if self._disconnect_callback is not None: self._disconnect_callback() def _connect(self, sock, addr, callback): self._reset() self._stream = DownStream(sock, io_loop=self._io_loop) self._stream.connect(addr, callback=callback, timeout=self.timeout) self._stream.read_until_close(self._on_close, self._on_read) def connect(self, sentinels=['localhost:6379'], master_name=None, callback=None, timeout=0.05): if not sentinels or not isinstance(sentinels, (list, tuple)): raise ValueError("sentinels must be a list with valid host:port values") if master_name is None or not master_name or not isinstance(master_name, six.string_types): raise ValueError("master_name argument must be a valid name") self.next_sentinel = 0 self.timeout = timeout self.sentinels = sentinels self.master_name = master_name self._connect_callback = callback self.connect_to_next_sentinel() def connect_to_next_sentinel(self): if self.next_sentinel < len(self.sentinels): host, port = self.sentinels[self.next_sentinel].split(':') self.next_sentinel += 1 else: if self._connect_callback: self.connection_status = "FAILED_AFTER_ALL_SENTINELS" self._connect_callback() self._connect_callback = None return try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) self._connect(sock, (host, int(port)), callback=self.handle_connection_to_sentinel) except socket.error: err = sys.exc_info()[1] if err.errno == errno.ECONNREFUSED: logger.warn("Error connecting to %s:%d (%s)... Trying next sentinel." % (host, int(port), err)) #self.connect_to_next_sentinel() else: raise def handle_connection_to_sentinel(self, *args, **kw): if not args[0]: self.connect_to_next_sentinel() return self.update_sentinels() def update_sentinels(self): self.send_message([ 'sentinel', 'sentinels', self.master_name ], self.handle_get_all_sentinels) def handle_get_all_sentinels(self, *args, **kw): # each sentinel is a tuple with the values below # 'name', '10.10.10.10:26379', 'ip', '10.10.10.10', 'port', '26379', 'runid', '7ae5839dec4ce7685b7db89d365e01b0b1dba28f', 'flags', 'sentinel', 'pending-commands', '0', 'last-ping-sent', '0', 'last-ok-ping-reply', '341', 'last-ping-reply', '341', 'down-after-milliseconds', '5000', 'last-hello-message', '300', 'voted-leader', '?', 'voted-leader-epoch', '0' sentinels = args[0] if isinstance(sentinels, Exception) and sentinels.message == 'ERR No such master with that name': self.connection_status = "NO_SUCH_MASTER_WITH_THAT_NAME" self.connection_error = sentinels.message self._connect_callback() self._connect_callback = None return if sentinels is not None: for sentinel in sentinels: name = sentinel[1] if name not in self.sentinels: self.sentinels.append(name) self.next_sentinel = 0 self.send_message([ 'sentinel', 'get-master-addr-by-name', self.master_name ], self.handle_get_master_address) def handle_get_master_address(self, *args, **kw): if args[0] is None or args[0] == '-IDONTKNOW': self.connect_to_next_sentinel() return master_host, master_port = args[0] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) self._connect(sock, (master_host, int(master_port)), self.handle_connection_success) def handle_connection_success(self, *args, **kw): if self._connect_callback: self.connection_status = "CONNECTED" self._connect_callback() self._connect_callback = None
class SentinelClient(Client): def __init__(self, io_loop=None, disconnect_callback=None): super(SentinelClient, self).__init__(io_loop=io_loop) self._disconnect_callback = disconnect_callback def on_disconnect(self): if self._disconnect_callback is not None: self._disconnect_callback() def _connect(self, sock, addr, callback): self._reset() self._stream = DownStream(sock, io_loop=self._io_loop) self._stream.connect(addr, callback=callback, timeout=self.timeout) self._stream.read_until_close(self._on_close, self._on_read) def connect(self, sentinels=['localhost:6379'], master_name=None, callback=None, timeout=0.05): if not sentinels or not isinstance(sentinels, (list, tuple)): raise ValueError("sentinels must be a list with valid host:port values") if master_name is None or not master_name or not isinstance(master_name, six.string_types): raise ValueError("master_name argument must be a valid name") if callback is None: raise ValueError("callback must be supplied and you should verify the `connection_status` property of the SentinelClient in your callback to make sure it's `CONNECTED`.") self.next_sentinel = 0 self.timeout = timeout self.sentinels = sentinels self.master_name = master_name self._connect_callback = callback self.connect_to_next_sentinel() def connect_to_next_sentinel(self): if self.next_sentinel < len(self.sentinels): host, port = self.sentinels[self.next_sentinel].split(':') self.next_sentinel += 1 else: if self._connect_callback: self.connection_status = "FAILED_AFTER_ALL_SENTINELS" self._connect_callback() self._connect_callback = None return try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) self._connect(sock, (host, int(port)), callback=self.handle_connection_to_sentinel) except socket.error: err = sys.exc_info()[1] if err.errno == errno.ECONNREFUSED: logger.warn("Error connecting to %s:%d (%s)... Trying next sentinel." % (host, int(port), err)) #self.connect_to_next_sentinel() else: raise def handle_connection_to_sentinel(self, *args, **kw): if not args[0]: self.connect_to_next_sentinel() return self.update_sentinels() def update_sentinels(self): self.send_message([ 'sentinel', 'sentinels', self.master_name ], self.handle_get_all_sentinels) def handle_get_all_sentinels(self, *args, **kw): # each sentinel is a tuple with the values below # 'name', '10.10.10.10:26379', 'ip', '10.10.10.10', 'port', '26379', 'runid', '7ae5839dec4ce7685b7db89d365e01b0b1dba28f', 'flags', 'sentinel', 'pending-commands', '0', 'last-ping-sent', '0', 'last-ok-ping-reply', '341', 'last-ping-reply', '341', 'down-after-milliseconds', '5000', 'last-hello-message', '300', 'voted-leader', '?', 'voted-leader-epoch', '0' sentinels = args[0] if isinstance(sentinels, Exception) and sentinels.message == 'ERR No such master with that name': self.connection_status = "NO_SUCH_MASTER_WITH_THAT_NAME" self.connection_error = sentinels.message self._connect_callback() self._connect_callback = None return if sentinels is not None: for sentinel in sentinels: name = sentinel[1] if name not in self.sentinels: self.sentinels.append(name) self.next_sentinel = 0 self.send_message([ 'sentinel', 'get-master-addr-by-name', self.master_name ], self.handle_get_master_address) def handle_get_master_address(self, *args, **kw): if args[0] is None or args[0] == '-IDONTKNOW': self.connect_to_next_sentinel() return master_host, master_port = args[0] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) self._connect(sock, (master_host, int(master_port)), self.handle_connection_success) def handle_connection_success(self, *args, **kw): if self._connect_callback: self.connection_status = "CONNECTED" self._connect_callback() self._connect_callback = None