def _connectToEndpoint(self, host, port, timeout, blocking=False): if self.isConnected(): raise IllegalStateError( 'service "{0}" is already connected'.format(self.name)) addressInfoList = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM) if not addressInfoList: raise ConnectionResolveError((host, port)) pipe_timeout = float(timeout) / len( addressInfoList) if timeout is not None else None log.debug('Connecting to the service "{0}", candidates: {1}'.format( self.name, addressInfoList)) start = time() errors = [] for family, socktype, proto, canonname, address in addressInfoList: log.debug(' - connecting to "{0} {1}"'.format(proto, address)) sock = socket.socket(family=family, type=socktype, proto=proto) try: self._pipe = Pipe(sock) yield self._pipe.connect(address, timeout=pipe_timeout, blocking=blocking) log.debug(' - success') except ConnectionError as err: errors.append(err) log.debug(' - failed - {0}'.format(err)) except Exception as err: log.warn( 'Unexpected error caught while connecting to the "{0}" - {1}' .format(address, err)) else: self._ioLoop = self._pipe._ioLoop self._writableStream = WritableStream(self._ioLoop, self._pipe) self._readableStream = ReadableStream(self._ioLoop, self._pipe) self._ioLoop.bind_on_fd(self._pipe.fileno()) def decode_and_dispatch(on_event): def dispatch(unpacker): for chunk in unpacker: on_event(chunk) return dispatch self._readableStream.bind(decode_and_dispatch( self._on_message)) return if timeout is not None and time() - start > timeout: raise ConnectionTimeoutError((host, port), timeout) prefix = 'service resolving failed. Reason:' reason = '{0} [{1}]'.format(prefix, ', '.join(str(err) for err in errors)) raise ConnectionError((host, port), reason)
def __init__(self, init_args=None, disown_timeout=2, heartbeat_timeout=20): self._logger = core_log self._init_endpoint(init_args or sys.argv) self.sessions = dict() self.sandbox = Sandbox() self.loop = ev.Loop() self.disown_timer = ev.Timer(self.on_disown, disown_timeout, self.loop) self.heartbeat_timer = ev.Timer(self.on_heartbeat, heartbeat_timeout, self.loop) self.heartbeat_timer.start() if isinstance(self.endpoint, types.TupleType) or isinstance(self.endpoint, types.ListType): if len(self.endpoint) == 2: socket_type = socket.AF_INET elif len(self.endpoint) == 4: socket_type = socket.AF_INET6 else: raise ValueError('invalid endpoint') elif isinstance(self.endpoint, types.StringType): socket_type = socket.AF_UNIX else: raise ValueError('invalid endpoint') sock = socket.socket(socket_type) self.pipe = Pipe(sock) self.pipe.connect(self.endpoint, blocking=True) self.loop.bind_on_fd(self.pipe.fileno()) self.decoder = Decoder() self.decoder.bind(self.on_message) self.w_stream = WritableStream(self.loop, self.pipe) self.r_stream = ReadableStream(self.loop, self.pipe) self.r_stream.bind(self.decoder.decode) self.loop.register_read_event(self.r_stream._on_event, self.pipe.fileno()) self._logger.debug("Worker with %s send handshake" % self.id) # Send both messages - to run timers properly. This messages will be sent # only after all initialization, so they have same purpose. self._send_handshake() self._send_heartbeat()