def msg_reply(conf, msg_id, reply_q, connection_pool, reply=None, failure=None, ending=False, log_failure=True): """Sends a reply or an error on the channel signified by msg_id. Failure should be a sys.exc_info() tuple. """ with ConnectionContext(conf, connection_pool) as conn: if failure: failure = rpc_common.serialize_remote_exception(failure, log_failure) try: msg = {'result': reply, 'failure': failure} except TypeError: msg = {'result': dict((k, repr(v)) for k, v in reply.__dict__.iteritems()), 'failure': failure} if ending: msg['ending'] = True _add_unique_id(msg) # If a reply_q exists, add the msg_id to the reply and pass the # reply_q to direct_send() to use it as the response queue. # Otherwise use the msg_id for backward compatibilty. if reply_q: msg['_msg_id'] = msg_id conn.direct_send(reply_q, rpc_common.serialize_msg(msg)) else: conn.direct_send(msg_id, rpc_common.serialize_msg(msg))
def multicall(conf, context, topic, msg, timeout, connection_pool): """Make a call that returns multiple times.""" # TODO(pekowski): Remove all these comments in Havana. # For amqp_rpc_single_reply_queue = False, # Can't use 'with' for multicall, as it returns an iterator # that will continue to use the connection. When it's done, # connection.close() will get called which will put it back into # the pool # For amqp_rpc_single_reply_queue = True, # The 'with' statement is mandatory for closing the connection LOG.debug(_('Making synchronous call on %s ...'), topic) msg_id = uuid.uuid4().hex msg.update({'_msg_id': msg_id}) LOG.debug(_('MSG_ID is %s') % (msg_id)) _add_unique_id(msg) pack_context(msg, context) # TODO(pekowski): Remove this flag and the code under the if clause # in Havana. if not conf.amqp_rpc_single_reply_queue: conn = ConnectionContext(conf, connection_pool) wait_msg = MulticallWaiter(conf, conn, timeout) conn.declare_direct_consumer(msg_id, wait_msg) conn.topic_send(topic, rpc_common.serialize_msg(msg), timeout) else: with _reply_proxy_create_sem: if not connection_pool.reply_proxy: connection_pool.reply_proxy = ReplyProxy(conf, connection_pool) msg.update({'_reply_q': connection_pool.reply_proxy.get_reply_q()}) wait_msg = MulticallProxyWaiter(conf, msg_id, timeout, connection_pool) with ConnectionContext(conf, connection_pool) as conn: conn.topic_send(topic, rpc_common.serialize_msg(msg), timeout) return wait_msg
def msg_reply(conf, msg_id, reply_q, connection_pool, reply=None, failure=None, ending=False, log_failure=True): """Sends a reply or an error on the channel signified by msg_id. Failure should be a sys.exc_info() tuple. """ with ConnectionContext(conf, connection_pool) as conn: if failure: failure = rpc_common.serialize_remote_exception( failure, log_failure) msg = {'result': reply, 'failure': failure} if ending: msg['ending'] = True _add_unique_id(msg) # If a reply_q exists, add the msg_id to the reply and pass the # reply_q to direct_send() to use it as the response queue. # Otherwise use the msg_id for backward compatibilty. if reply_q: msg['_msg_id'] = msg_id conn.direct_send(reply_q, rpc_common.serialize_msg(msg)) else: conn.direct_send(msg_id, rpc_common.serialize_msg(msg))
def test_serialize_msg_v2(self): msg = {'foo': 'bar'} s_msg = {'oslo.version': rpc_common._RPC_ENVELOPE_VERSION, 'oslo.message': jsonutils.dumps(msg)} serialized = rpc_common.serialize_msg(msg) self.assertEqual(s_msg, rpc_common.serialize_msg(msg)) self.assertEqual(msg, rpc_common.deserialize_msg(serialized))
def cast(conf, context, topic, msg, connection_pool): """Sends a message on a topic without waiting for a response.""" LOG.debug('Making asynchronous cast on %s...', topic) _add_unique_id(msg) pack_context(msg, context) with ConnectionContext(conf, connection_pool) as conn: conn.topic_send(topic, rpc_common.serialize_msg(msg))
def fanout_cast(conf, context, topic, msg, connection_pool): """Sends a message on a fanout exchange without waiting for a response.""" LOG.debug('Making asynchronous fanout cast...') _add_unique_id(msg) pack_context(msg, context) with ConnectionContext(conf, connection_pool) as conn: conn.fanout_send(topic, rpc_common.serialize_msg(msg))
def cast_to_server(conf, context, server_params, topic, msg, connection_pool): """Sends a message on a topic to a specific server.""" _add_unique_id(msg) pack_context(msg, context) with ConnectionContext(conf, connection_pool, pooled=False, server_params=server_params) as conn: conn.topic_send(topic, rpc_common.serialize_msg(msg))
def test_topic_multiple_queues_specify_exchange(self): """Test sending to a topic exchange with multiple queues and one exchange """ conn = self.rpc.create_connection(FLAGS) message = "topic test message" self.received_message_1 = None self.received_message_2 = None def _callback1(message): self.received_message_1 = message def _callback2(message): self.received_message_2 = message conn.declare_topic_consumer("a_topic", _callback1, queue_name="queue1", exchange_name="abc") conn.declare_topic_consumer("a_topic", _callback2, queue_name="queue2", exchange_name="abc") conn.topic_send("a_topic", rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() self.assertEqual(self.received_message_1, message) self.assertEqual(self.received_message_2, message)
def fanout_cast_to_server(conf, context, server_params, topic, msg, connection_pool): """Sends a message on a fanout exchange to a specific server.""" pack_context(msg, context) with ConnectionContext(conf, connection_pool, pooled=False, server_params=server_params) as conn: conn.fanout_send(topic, rpc_common.serialize_msg(msg))
def test_topic_one_queues_multiple_exchange(self): """Test sending to a topic exchange with one queues and several exchanges """ conn = self.rpc.create_connection(self.FLAGS) message = 'topic test message' self.received_message_1 = None self.received_message_2 = None def _callback1(message): self.received_message_1 = message def _callback2(message): self.received_message_2 = message conn.declare_topic_consumer('a_topic', _callback1, queue_name='queue1', exchange_name="abc") conn.declare_topic_consumer('a_topic', _callback2, queue_name='queue2', exchange_name="def") conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() self.assertEqual(self.received_message_1, message) self.assertEqual(self.received_message_2, message)
def test_topic_one_queues_multiple_exchange(self): """Test sending to a topic exchange with one queues and several exchanges """ conn = self.rpc.create_connection(FLAGS) message = 'topic test message' self.received_message_1 = None self.received_message_2 = None def _callback1(message): self.received_message_1 = message def _callback2(message): self.received_message_2 = message conn.declare_topic_consumer('a_topic', _callback1, queue_name='queue1', exchange_name="abc") conn.declare_topic_consumer('a_topic', _callback2, queue_name='queue2', exchange_name="def") conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() self.assertEqual(self.received_message_1, message) self.assertEqual(self.received_message_2, message)
def fanout_cast(conf, context, topic, msg, connection_pool): """Sends a message on a fanout exchange without waiting for a response.""" LOG.debug(_('Making asynchronous fanout cast...')) _add_unique_id(msg) pack_context(msg, context) with ConnectionContext(conf, connection_pool) as conn: conn.fanout_send(topic, rpc_common.serialize_msg(msg))
def cast(conf, context, topic, msg, connection_pool): """Sends a message on a topic without waiting for a response.""" LOG.debug(_('Making asynchronous cast on %s...'), topic) _add_unique_id(msg) pack_context(msg, context) with ConnectionContext(conf, connection_pool) as conn: conn.topic_send(topic, rpc_common.serialize_msg(msg))
def cast(self, msg_id, topic, data, serialize=True, force_envelope=False): if serialize: data = rpc_common.serialize_msg(data, force_envelope) self.outq.send( [str(msg_id), str(topic), str('cast'), _serialize(data)])
def notify(conf, context, topic, msg, connection_pool, envelope): """Sends a notification event on a topic.""" LOG.debug(_('Sending %(event_type)s on %(topic)s'), dict(event_type=msg.get('event_type'), topic=topic)) pack_context(msg, context) with ConnectionContext(conf, connection_pool) as conn: if envelope: msg = rpc_common.serialize_msg(msg, force_envelope=True) conn.notify_send(topic, msg)
def notify(conf, context, topic, msg, connection_pool, envelope): """Sends a notification event on a topic.""" LOG.debug(_('Sending %(event_type)s on %(topic)s'), dict(event_type=msg.get('event_type'), topic=topic)) _add_unique_id(msg) pack_context(msg, context) with ConnectionContext(conf, connection_pool) as conn: if envelope: msg = rpc_common.serialize_msg(msg) conn.notify_send(topic, msg)
def cast(self, msg_id, topic, data, envelope=False): msg_id = msg_id or 0 if not envelope: self.outq.send(map(bytes, (msg_id, topic, 'cast', _serialize(data)))) return rpc_envelope = rpc_common.serialize_msg(data[1], envelope) zmq_msg = reduce(lambda x, y: x + y, rpc_envelope.items()) self.outq.send(map(bytes, (msg_id, topic, 'impl_zmq_v2', data[0]) + zmq_msg))
def cast(self, msg_id, topic, data, envelope): msg_id = msg_id or 0 if not envelope: self.outq.send(map(bytes, (msg_id, topic, 'cast', _serialize(data)))) return rpc_envelope = rpc_common.serialize_msg(data[1], envelope) zmq_msg = moves.reduce(lambda x, y: x + y, rpc_envelope.items()) self.outq.send(map(bytes, (msg_id, topic, 'impl_zmq_v2', data[0]) + zmq_msg))
def test_duplicate_message_check(self): """Test sending *not-dict* to a topic exchange/queue.""" conn = self.rpc.create_connection(FLAGS) message = {'args': 'topic test message', '_unique_id': 'aaaabbbbcccc'} self.received_message = None cache = rpc_amqp._MsgIdCache() self.exc_raised = False def _callback(message): try: cache.check_duplicate_message(message) except rpc_common.DuplicateMessageError: self.exc_raised = True conn.declare_topic_consumer('a_topic', _callback) conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() self.assertTrue(self.exc_raised)
def test_direct_send_receive(self): """Test sending to a direct exchange/queue""" conn = self.rpc.create_connection(FLAGS) message = 'direct test message' self.received_message = None def _callback(message): self.received_message = message conn.declare_direct_consumer('a_direct', _callback) conn.direct_send('a_direct', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def test_direct_send_receive(self): """Test sending to a direct exchange/queue.""" conn = self.rpc.create_connection(self.FLAGS) message = 'direct test message' self.received_message = None def _callback(message): self.received_message = message conn.declare_direct_consumer('a_direct', _callback) conn.direct_send('a_direct', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def multicall(conf, context, topic, msg, timeout, connection_pool): """Make a call that returns multiple times.""" LOG.debug(_('Making synchronous call on %s ...'), topic) msg_id = uuid.uuid4().hex msg.update({'_msg_id': msg_id}) LOG.debug(_('MSG_ID is %s') % (msg_id)) _add_unique_id(msg) pack_context(msg, context) with _reply_proxy_create_sem: if not connection_pool.reply_proxy: connection_pool.reply_proxy = ReplyProxy(conf, connection_pool) msg.update({'_reply_q': connection_pool.reply_proxy.get_reply_q()}) wait_msg = MulticallProxyWaiter(conf, msg_id, timeout, connection_pool) with ConnectionContext(conf, connection_pool) as conn: conn.topic_send(topic, rpc_common.serialize_msg(msg), timeout) return wait_msg
def test_message_ttl_on_timeout(self): """Test message ttl being set by request timeout. The message should die on the vine and never arrive.""" conn = self.rpc.create_connection(FLAGS) message = 'topic test message' self.received_message = None def _callback(message): self.received_message = message self.fail("should not have received this message") conn.declare_topic_consumer('a_topic', _callback) conn.topic_send('a_topic', rpc_common.serialize_msg(message), 0) conn.iterconsume(1, 2) conn.close()
def test_topic_send_receive(self): """Test sending to a topic exchange/queue""" conn = self.rpc.create_connection(FLAGS) message = "topic test message" self.received_message = None def _callback(message): self.received_message = message conn.declare_topic_consumer("a_topic", _callback) conn.topic_send("a_topic", rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def test_iterconsume_errors_will_reconnect(self): conn = self.rpc.Connection(FLAGS) message = "reconnect test message" self.received_message = None def _callback(message): self.received_message = message conn.declare_direct_consumer("a_direct", _callback) conn.direct_send("a_direct", rpc_common.serialize_msg(message)) info = _raise_exc_stub(self.stubs, 1, conn.connection, "drain_events", "foo timeout foo") conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def multicall(conf, context, topic, msg, timeout, connection_pool): """Make a call that returns multiple times.""" # Can't use 'with' for multicall, as it returns an iterator # that will continue to use the connection. When it's done, # connection.close() will get called which will put it back into # the pool LOG.debug(_('Making synchronous call on %s ...'), topic) msg_id = uuid.uuid4().hex msg.update({'_msg_id': msg_id}) LOG.debug(_('MSG_ID is %s') % (msg_id)) pack_context(msg, context) conn = ConnectionContext(conf, connection_pool) wait_msg = MulticallWaiter(conf, conn, timeout) conn.declare_direct_consumer(msg_id, wait_msg) conn.topic_send(topic, rpc_common.serialize_msg(msg), timeout) return wait_msg
def multicall(conf, context, topic, msg, timeout, connection_pool): """Make a call that returns multiple times.""" # Can't use 'with' for multicall, as it returns an iterator # that will continue to use the connection. When it's done, # connection.close() will get called which will put it back into # the pool LOG.debug(_('Making synchronous call on %s ...'), topic) msg_id = uuid.uuid4().hex msg.update({'_msg_id': msg_id}) LOG.debug(_('MSG_ID is %s') % (msg_id)) pack_context(msg, context) conn = ConnectionContext(conf, connection_pool) wait_msg = MulticallWaiter(conf, conn, timeout) conn.declare_direct_consumer(msg_id, wait_msg) conn.topic_send(topic, rpc_common.serialize_msg(msg)) return wait_msg
def multicall(conf, context, topic, msg, timeout, connection_pool): """Make a call that returns multiple times.""" LOG.debug('Making synchronous call on %s ...', topic) msg_id = uuid.uuid4().hex msg.update({'_msg_id': msg_id}) LOG.debug('MSG_ID is %s' % (msg_id)) _add_unique_id(msg) pack_context(msg, context) with _reply_proxy_create_sem: if not connection_pool.reply_proxy: connection_pool.reply_proxy = ReplyProxy(conf, connection_pool) msg.update({'_reply_q': connection_pool.reply_proxy.get_reply_q()}) wait_msg = MulticallProxyWaiter(conf, msg_id, timeout, connection_pool) with ConnectionContext(conf, connection_pool) as conn: conn.topic_send(topic, rpc_common.serialize_msg(msg), timeout) return wait_msg
def test_topic_send_receive_exchange_name(self): """Test sending to a topic exchange/queue with an exchange name.""" conn = self.rpc.create_connection(self.FLAGS) message = 'topic test message' self.received_message = None def _callback(message): self.received_message = message conn.declare_topic_consumer('a_topic', _callback, exchange_name="foorbar") conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def test_topic_send_receive_exchange_name(self): """Test sending to a topic exchange/queue with an exchange name""" conn = self.rpc.create_connection(FLAGS) message = 'topic test message' self.received_message = None def _callback(message): self.received_message = message conn.declare_topic_consumer('a_topic', _callback, exchange_name="foorbar") conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def test_iterconsume_errors_will_reconnect(self): conn = self.rpc.Connection(self.FLAGS) message = 'reconnect test message' self.received_message = None def _callback(message): self.received_message = message conn.declare_direct_consumer('a_direct', _callback) conn.direct_send('a_direct', rpc_common.serialize_msg(message)) _raise_exc_stub(self.stubs, 1, conn.connection, 'drain_events', 'foo timeout foo') conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def test_iterconsume_errors_will_reconnect(self): conn = self.rpc.Connection(FLAGS) message = 'reconnect test message' self.received_message = None def _callback(message): self.received_message = message conn.declare_direct_consumer('a_direct', _callback) conn.direct_send('a_direct', rpc_common.serialize_msg(message)) info = _raise_exc_stub(self.stubs, 1, conn.connection, 'drain_events', 'foo timeout foo') conn.consume(limit=1) conn.close() self.assertEqual(self.received_message, message)
def msg_reply(conf, msg_id, connection_pool, reply=None, failure=None, ending=False, log_failure=True): """Sends a reply or an error on the channel signified by msg_id. Failure should be a sys.exc_info() tuple. """ with ConnectionContext(conf, connection_pool) as conn: if failure: failure = rpc_common.serialize_remote_exception(failure, log_failure) try: msg = {'result': reply, 'failure': failure} except TypeError: msg = {'result': dict((k, repr(v)) for k, v in reply.__dict__.iteritems()), 'failure': failure} if ending: msg['ending'] = True conn.direct_send(msg_id, rpc_common.serialize_msg(msg))
def cast(self, msg_id, topic, data, serialize=True, force_envelope=False): if serialize: data = rpc_common.serialize_msg(data, force_envelope) self.outq.send([str(msg_id), str(topic), str('cast'), _serialize(data)])
def cast(self, msg_id, topic, data, serialize=True, force_envelope=False): msg_id = msg_id or 0 if serialize: data = rpc_common.serialize_msg(data, force_envelope) self.outq.send(map(bytes, (msg_id, topic, 'cast', _serialize(data))))
def test_serialize_msg_v1(self): self.stubs.Set(rpc_common, '_SEND_RPC_ENVELOPE', False) msg = {'foo': 'bar'} self.assertEqual(msg, rpc_common.serialize_msg(msg))