def test_deserialize_to_remote_error(): exc = CustomError('something went wrong') data = serialize(exc) deserialized = deserialize(data) assert type(deserialized) == RemoteError assert deserialized.exc_type == "CustomError" assert deserialized.value == "something went wrong" assert str(deserialized) == "CustomError something went wrong"
def test_deserialize_to_remote_error(): exc = CustomError(u'something went ಠ_ಠ') data = serialize(exc) deserialized = deserialize(data) assert type(deserialized) == RemoteError assert deserialized.exc_type == "CustomError" assert deserialized.value == u"something went ಠ_ಠ" assert six.text_type(deserialized) == u"CustomError something went ಠ_ಠ"
def result(self): _log.debug('Waiting for RPC reply event %s', self) if self.resp_body is None: self.resp_body = self.reply_event.wait() _log.debug('RPC reply event complete %s %s', self, self.resp_body) error = self.resp_body.get('error') if error: raise deserialize(error) return self.resp_body['result']
def test_deserialize_to_instance(): # register Error as deserializable to an instance deserialize_to_instance(CustomError) exc = CustomError('something went wrong') data = serialize(exc) deserialized = deserialize(data) assert type(deserialized) == CustomError assert str(deserialized) == "something went wrong"
def test_exception_name_clash(): class MethodNotFound(Exception): # application exception with clashing name pass exc = MethodNotFound('application error') data = serialize(exc) deserialized = deserialize(data) assert type(deserialized) == RemoteError assert deserialized.exc_type == "MethodNotFound" assert deserialized.value == "application error" assert str(deserialized) == "MethodNotFound application error" from nameko.exceptions import MethodNotFound as NamekoMethodNotFound exc = NamekoMethodNotFound('missing') data = serialize(exc) deserialized = deserialize(data) assert type(deserialized) == NamekoMethodNotFound assert str(deserialized) == "missing"
def test_serialize_backwards_compat(): exc = CustomError('something went wrong') data = serialize(exc) # nameko < 1.5.0 has no ``exc_path`` or ``exc_args`` keys del data['exc_path'] del data['exc_args'] deserialized = deserialize(data) assert type(deserialized) == RemoteError assert deserialized.exc_type == "CustomError" assert deserialized.value == "something went wrong" assert str(deserialized) == "CustomError something went wrong" # nameko < 1.1.4 has an extra ``traceback`` key data['traceback'] = "traceback string" deserialized = deserialize(data) assert type(deserialized) == RemoteError assert deserialized.exc_type == "CustomError" assert deserialized.value == "something went wrong" assert str(deserialized) == "CustomError something went wrong"
def rpc(self, _method, **data): id = str(uuid.uuid4()) event = Event() result_handlers[id] = event.send ws_app.send(json.dumps({ 'method': _method, 'data': data, 'correlation_id': id, })) rv = event.wait() if rv['success']: return rv['data'] raise deserialize(rv['error'])
def rpc(self, _method, **data): id = str(uuid.uuid4()) event = Event() result_handlers[id] = event.send ws_app.send( json.dumps({ 'method': _method, 'data': data, 'correlation_id': id, })) rv = event.wait() if rv['success']: return rv['data'] raise deserialize(rv['error'])
def __call__(self, *args, **kwargs): _log.debug('invoking %s', self) worker_ctx = self.worker_ctx container = worker_ctx.container msg = {'args': args, 'kwargs': kwargs} conn = Connection( container.config[AMQP_URI_CONFIG_KEY], transport_options={'confirm_publish': True}, ) # We use the `mandatory` flag in `producer.publish` below to catch rpc # calls to non-existent services, which would otherwise wait forever # for a reply that will never arrive. # # However, the basic.return ("no one is listening for topic") is sent # asynchronously and conditionally, so we can't wait() on the channel # for it (will wait forever on successful delivery). # # Instead, we use (the rabbitmq extension) confirm_publish # (https://www.rabbitmq.com/confirms.html), which _always_ sends a # reply down the channel. Moreover, in the case where no queues are # bound to the exchange (service unknown), the basic.return is sent # first, so by the time kombu returns (after waiting for the confim) # we can reliably check for returned messages. routing_key = '{}.{}'.format(self.service_name, self.method_name) exchange = get_rpc_exchange(container) with producers[conn].acquire(block=True) as producer: headers = self.get_message_headers(worker_ctx) correlation_id = str(uuid.uuid4()) reply_listener = self.reply_listener reply_to_routing_key = reply_listener.routing_key reply_event = reply_listener.get_reply_event(correlation_id) producer.publish( msg, exchange=exchange, routing_key=routing_key, mandatory=True, reply_to=reply_to_routing_key, headers=headers, correlation_id=correlation_id, retry=True, retry_policy=DEFAULT_RETRY_POLICY ) if not producer.channel.returned_messages.empty(): raise UnknownService(self.service_name) _log.debug('Waiting for RPC reply event %s', self) resp_body = reply_event.wait() _log.debug('RPC reply event complete %s %s', self, resp_body) error = resp_body.get('error') if error: raise deserialize(error) return resp_body['result']
def on_message(ws, message): response = json.loads(message) assert not response['success'] exc = deserialize(response['error']) result.send_exception(exc)