async def _execute_node(self, pool, command, *args, **kwargs): """Execute redis command and returns Future waiting for the answer. :param command str :param pool obj Raises: * TypeError if any of args can not be encoded as bytes. * ReplyError on redis '-ERR' responses. * ProtocolError when response can not be decoded meaning connection is broken. """ cmd = decode(command, 'utf-8').lower() try: with await pool as conn: return await getattr(conn, cmd)(*args, **kwargs) except ReplyError as err: address = parse_moved_response_error(err) if address is None: raise logger.debug('Got MOVED command: {}'.format(err)) self._moved_count += 1 if self._moved_count >= self.MAX_MOVED_COUNT: await self.initialize() pool = self.get_node(command, *args, **kwargs) with await pool as conn: return await getattr(conn, cmd)(*args, **kwargs) else: conn = await self.create_connection(address) res = await getattr(conn, cmd)(*args, **kwargs) conn.close() await conn.wait_closed() return res
def _assign_slots(self, masters, addresses): slot_boundaries = [ math.floor(i * REDIS_SLOT_COUNT / len(masters)) for i in range(len(masters) + 1) ] slot_ranges = [ range(b1, b2) for b1, b2 in zip(slot_boundaries, slot_boundaries[1:]) ] for master, slot_range, address in zip(masters, slot_ranges, addresses): logger.debug("Assigning master at {} slots {}-{}".format( address, slot_range.start, slot_range.stop - 1)) slots = ' '.join(str(slot) for slot in slot_range) try: self._send_command_and_expect_ok( master, 'CLUSTER ADDSLOTS {}\r\n'.format(slots)) except IOError as e: raise IOError( "ADDSLOTS failed. Maybe a cluster is already running? " "({}).".format(str(e)))
def _determine_node_id(self, socket, address): socket.sendall(b'CLUSTER NODES\r\n') data = self._read_bulk_string_response(socket) node_id = data[:40].decode('utf-8') logger.debug("Master at {} has node id {}.".format(address, node_id)) return node_id