Beispiel #1
0
    def send_and_recv(self,
                      method,
                      endpoint,
                      parameters=None,
                      data=None,
                      decode_response=True):
        logger.debug('Request: {} {}'.format(method, endpoint))
        message = {
            'method': method,
            'endpoint': endpoint,
        }

        if parameters:
            message['parameters'] = parameters

        if data:
            message['data'] = data

        self._socket.send(msgpack.packb(message))
        zmq_response = get_data_from_zmq(self._socket, self._timeout)
        zmq_response = msgpack.unpackb(zmq_response)
        if decode_response:
            response = Response(decode(zmq_response[b'response']),
                                decode(zmq_response[b'status']))
        else:
            response = Response(zmq_response[b'response'],
                                zmq_response[b'status'])
        logger.debug('Response: {} - {}'.format(str(response.status_code),
                                                str(response.response)))
        return response
Beispiel #2
0
 def __init__(self, source, content):
     self._id = uuid.uuid4().hex  # str
     self._source = copy.deepcopy(source)  # list of bytes
     self._content = msgpack.unpackb(content)  # dictionary of bytes
     self._method = decode(self._content[b'method'])  # str
     self._endpoint = decode(self._content[b'endpoint'])  # str
     logger.debug('Creating or loading ClientRequest {}@{}: {}/{}'.format(
         self._id, self._endpoint, self._source, self._content))
Beispiel #3
0
 def __init__(self, request):
     self._id = decode(request[b'id'])  # str
     self._method = decode(request[b'method'])  # str
     self._endpoint = decode(request[b'endpoint'])  # str
     if b'parameters' in request:
         self._parameters = decode(request[b'parameters'])  # dict of str
     else:
         self._parameters = {}
     if b'data' in request:
         self._data = request[b'data']  # dict of bytes
     else:
         self._data = {}
Beispiel #4
0
    def run(self):
        self._connect()

        poller = zmq.Poller()
        poller.register(self._socket_control, zmq.POLLIN)

        logger.info('Starting with endpoints {}'.format(ctx_request.endpoints))

        state_manager = BrokerStateManager(
            seconds_before_contact_check=SECONDS_BEFORE_CONTACT_CHECK,
            seconds_before_disconnect=SECONDS_BEFORE_DISCONNECT)

        loop = True
        init_connection = True

        poller_timeout = max([
            int(
                min([SECONDS_BEFORE_CONTACT_CHECK, SECONDS_BEFORE_DISCONNECT])
                / 10.0 * 1000), 500
        ])

        while loop:
            if init_connection:
                self._socket_control.send_multipart([
                    b'',
                    msgpack.packb({
                        'endpoints': ctx_request.endpoints,
                        'w': True
                    })
                ])
                init_connection = False

            sockets = dict(poller.poll(poller_timeout))

            # if sockets:
            #     logger.debug('Received: {}'.format(sockets))

            if self._socket_control in sockets and sockets[
                    self._socket_control] == zmq.POLLIN:
                # get message content
                content = extract_content_from_message(
                    self._socket_control.recv_multipart())
                content = msgpack.unpackb(content)

                state_manager.contact_from_broker()

                # process control messages
                if b'control' in content:
                    control = decode(content[b'control'])
                    if control == 'ping':
                        # logger.debug('Received ping from broker')
                        self._socket_control.send_multipart(
                            [b'', msgpack.packb({'pong': True})])
                    elif control == 'pong':
                        # logger.debug('Received pong from broker')
                        pass
                    elif control == 'kick':
                        init_connection = True

                # process client request messages
                else:
                    message = Request(content)
                    self._socket_control.send_multipart(
                        [b'', msgpack.packb({'r': message.id})])
                    try:
                        logger.info('Received: {} {}'.format(
                            message.method, message.endpoint))
                        service = ctx_request.get_service_by_endpoint(
                            message.endpoint, message.method)
                        response = service(message)
                        if isinstance(response, tuple):
                            response, status = response
                        else:
                            status = codes.OK
                    except RequestError as e:
                        response = str(e)
                        status = e.status_code
                    except:
                        logger.error(sys.exc_info()[0])
                        logger.error(sys.exc_info()[1])
                        logger.error(traceback.extract_tb(sys.exc_info()[2]))
                        response = {}
                        status = codes.SERVER_ERROR
                    self._socket_response.send(
                        msgpack.packb({
                            'id': message.id,
                            'status': status,
                            'response': response
                        }))
                    self._socket_control.send_multipart(
                        [b'', msgpack.packb({'w': True})])
                    self._socket_response.recv()

            if state_manager.ping_broker():
                # logger.debug('Pinging broker')
                self._socket_control.send_multipart(
                    [b'', msgpack.packb({'ping': True})])

            if state_manager.disconnect_broker():
                logger.info('Disconnecting from broker')
                self._socket_control.send_multipart(
                    [b'', msgpack.packb({'disconnect': True})])
                raise RuntimeError
Beispiel #5
0
 def __init__(self, publication):
     publication = msgpack.unpackb(publication)
     self._id = decode(publication[b'id'])  # str
     self._topic = decode(publication[b'topic'])  # str
     self._data = publication[b'data']  # dict of bytes
Beispiel #6
0
    def run(self):
        poller = zmq.Poller()
        poller.register(self._client_socket, zmq.POLLIN)
        poller.register(self._worker_control_socket, zmq.POLLIN)
        poller.register(self._worker_response_socket, zmq.POLLIN)

        request_manager = RequestManager(redis_host=self._redis_host,
                                         redis_port=self._redis_port,
                                         redis_db=self._redis_db)

        state_manager = ConnectionStateManager(
            seconds_before_contact_check=SECONDS_BEFORE_CONTACT_CHECK,
            seconds_before_disconnect=SECONDS_BEFORE_UNREGISTER)

        poller_timeout = max([
            int(
                min([SECONDS_BEFORE_CONTACT_CHECK, SECONDS_BEFORE_UNREGISTER])
                / 10.0 * 1000), 500
        ])
        loop = True
        while loop:
            sockets = dict(poller.poll(poller_timeout))

            # get a new client request
            if self._client_socket in sockets and sockets[
                    self._client_socket] == zmq.POLLIN:
                message = self._client_socket.recv_multipart()
                client_request = ClientRequest(
                    source=extract_source_from_message(message),
                    content=extract_content_from_message(message))
                request_manager.append(client_request)

            # register endpoints of a worker or mark the worker as waiting
            if self._worker_control_socket in sockets and sockets[
                    self._worker_control_socket] == zmq.POLLIN:
                message = self._worker_control_socket.recv_multipart()
                source = extract_source_from_message(message)
                content = extract_content_from_message(message)

                assert len(source) == 1
                worker_id = source[0]
                content = decode(msgpack.unpackb(content))

                state_manager.contact_from(worker_id)

                if 'endpoints' in content:
                    # first connection to register endpoints
                    request_manager.register(worker_id, content['endpoints'])

                if 'ping' in content and content['ping']:
                    # ping to check if broker is still available
                    logger.debug('Received ping from {}'.format(worker_id))
                    if worker_id in request_manager.registered_workers:
                        # only respond to registered workers, otherwise disconnect
                        self._worker_control_socket.send_multipart([
                            worker_id, b'',
                            msgpack.packb(
                                ControlRequest(ControlRequest.PONG).content)
                        ])
                    else:
                        # we don't know this worker, so remove it
                        self.send_kick(worker_id)
                        state_manager.disconnect(worker_id)

                if 'pong' in content and content['pong']:
                    logger.debug('Received pong from {}'.format(worker_id))

                if 'disconnect' in content and content['disconnect']:
                    # disconnect worker
                    request_manager.unregister(worker_id)
                    state_manager.disconnect(worker_id)

                if 'r' in content:
                    # acknowledge reception of task
                    pass

                if 'w' in content and content['w']:
                    # signal that task is done
                    request_manager.worker_available(worker_id)

            # receive responses and send them back to the client
            if self._worker_response_socket in sockets and sockets[
                    self._worker_response_socket] == zmq.POLLIN:
                message = self._worker_response_socket.recv_multipart()
                source = extract_source_from_message(message)
                response = extract_content_from_message(message)
                response = msgpack.unpackb(response)

                worker_response = source + [b''] + [b'OK']
                self._worker_response_socket.send_multipart(worker_response)

                request = request_manager[response[b'id'].decode()]
                del request_manager[response[b'id'].decode()]
                del response[b'id']

                client_response = request.source + [b''] + [
                    msgpack.packb(response)
                ]
                self._client_socket.send_multipart(client_response)

            # send requests to workers
            for worker_id, request in request_manager():
                logger.info('Sending {} to {}'.format(request.id, worker_id))
                self.send_request(worker_id, request)

            # send ping messages to workers
            for worker_id in state_manager.get_connections_to_ping():
                logger.debug('Pinging {}'.format(worker_id))
                self.send_ping(worker_id)

            # send kick messages to non-responsive workers
            for worker_id in state_manager.get_connections_to_disconnect():
                logger.info('Kicking {}'.format(worker_id))
                self.send_kick(worker_id)
                request_manager.unregister(worker_id)