Making a one-way rpc-like entrypoint

Hi,

How can the "rpc" decorator (Rpc class) be tweaked in a way that it does not create a reply queue and send responses?
Some of our service methods are one-way and we don't want/need the overhead of reply queues.

Thanks

If you're doing service-to-service RPC there's really not much overhead in
the reply queue -- it's created once and used for all replies to that
service. You'd only be saving the publishing of the response.

It's also fairly easy to implement one-way messaging using the
nameko.messaging.Publisher DependencyProvider and nameko.messaging.Consume
Entrypoint. These give you pretty low-level access to AMQP, using whatever
exchanges, queues and routing keys you like. I'd start with a subclass of
these. You can then add RPC-style encoding of the payload into args and
kwargs by lifting
https://github.com/nameko/nameko/blob/master/nameko/rpc.py#L372 and
https://github.com/nameko/nameko/blob/master/nameko/rpc.py#L158-L165.

···

On Tuesday, November 15, 2016 at 12:34:02 PM UTC, tsachi...@gmail.com wrote:

Hi,

How can the "rpc" decorator (Rpc class) be tweaked in a way that it does
not create a reply queue and send responses?
Some of our service methods are one-way and we don't want/need the
overhead of reply queues.

Thanks

Thanks Matt,

The use case is of clients using ClusterRpcProxy to send messages to a nameko cluster.
Some types of messages don't require a response (send and forget), so I want to remove any unnecessary overheads, such as creating reply queues.

To follow up with this topic, we are now experimenting with no-reply
entrypoint.
The way we implemented it is like this:

class NoReplyRpc(Rpc):
   def handle_result(self, message, worker_ctx, result, exc_info):
       self.rpc_consumer.queue_consumer.ack_message(message)
       return result, exc_info

no_reply_rpc = NoReplyRpc.decorator

Basically the change here is removing the rpc_consumer call in
handle_result().

Client implementation uses a simple producer (from kombu) to push messages
to the service queue, adding the correct routing key and empty 'reply_to'
and 'correlation_id' keys.

Our tests look ok, but I'd like to hear your opinion too.
Do you see any problem with such a solution?

This looks like a fine implementation to me.

Nameko RPC essentially boils down to:

On the client side:

1) Create reply queue
2) Publish a message containing the request to the service exchange...
a) ... using routing key to identify the method
b) ... setting reply-to to specify the queue to receive the reply
c) ... setting correlation-id so the client can pipeline requests and
identify the replies
3) Consume messages from the reply-to queue, and map them back to requests
using the correlation-id

On the server side:

1) Consume request messages from the service queue...
a) ... fire the appropriate entrypoint according to the routing key
2) Publish a message containing the response to the service exchange...
a) ... using reply-to as the routing key so the response ends up in the
correct queue
b) ... setting correlation-id so the client can identify the replies
3) ack the request message

For "no reply" RPC you drop 1, 2b, 2c and 3 on the client side, and 2a and
2b on the server side. Which is exactly what your implementation does.

···

On Thursday, February 9, 2017 at 8:23:49 AM UTC, tsachi...@gmail.com wrote:

To follow up with this topic, we are now experimenting with no-reply
entrypoint.
The way we implemented it is like this:

class NoReplyRpc(Rpc):
   def handle_result(self, message, worker_ctx, result, exc_info):
       self.rpc_consumer.queue_consumer.ack_message(message)
       return result, exc_info

no_reply_rpc = NoReplyRpc.decorator

Basically the change here is removing the rpc_consumer call in
handle_result().

Client implementation uses a simple producer (from kombu) to push messages
to the service queue, adding the correct routing key and empty 'reply_to'
and 'correlation_id' keys.

Our tests look ok, but I'd like to hear your opinion too.
Do you see any problem with such a solution?