Esempio n. 1
0
    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)
Esempio n. 2
0
    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()