Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NatsConnection.request(Message) does not use Message.replyTo #445

Closed
malloth opened this issue Apr 3, 2021 · 4 comments
Closed

NatsConnection.request(Message) does not use Message.replyTo #445

malloth opened this issue Apr 3, 2021 · 4 comments
Assignees

Comments

@malloth
Copy link

malloth commented Apr 3, 2021

In the newest version of the NATS client (2.10.0) I was hoping that this was finally fixed but I see you are still not using the Message.replyTo field properly.

Below code doesn't work at all, when you expect that server will reply on a different subject:

val response = conn.request(
    NatsMessage(
        requestSubject,
        responseSubject,
        payload.toByteArray(),
        conn.options.supportUTF8Subjects()
    ),
    Duration.ofMillis(5000L)
)

while this one does:

val subscription = conn.subscribe(responseSubject)
val response = try {
    val timeout = Duration.ofMillis(5000L)
    conn.publish(requestSubject, payload.toByteArray())
    conn.flush(timeout)
    subscription.nextMessage(timeout)
} finally {
    if (subscription.isActive) {
        subscription.unsubscribe()
    }
}

I expect the request() method to work like the code with a simple subscribe-publish. Can you please fix that?

If there's no replyTo then you can use the Inbox approach, but if there is then you should change the logic to expect the answer on a different subject.

Also would it be possible to also add a method request(String, String, byte[], Duration): Message which 2nd param would be the replyTo subject string?

@scottf
Copy link
Contributor

scottf commented Apr 3, 2021

@malloth Maybe. For now I'm going to treat this as a feature request. As far as I know the intention was not for users to use the reply to field, and this is a documentation issue and possibly demoting the public interface of both the constructor and the builder. I will check with the product manager. This may also explain why there is no request method that takes a reply to and there are no examples showing this. Can you maybe present a use case why you need this? I can't think of any reason you need to set the reply to, it is in fact an internal piece of information, and there may even be a server specific reason why we should not allow this. If we decided to do it, it's probably something I can fix this week and get you a snapshot.

@malloth
Copy link
Author

malloth commented Apr 4, 2021

@scottf The use case is very simple. We are using the chain of responsibility design pattern and for each client request (subject A) we receive response (subject B) which will be used to make another set of requests. We use it in payment terminals in this way: terminal (client) takes credit card payment and sends a request with payment info (<domain>.PaymentInfo) to the server and awaits for tip message from the sever (<domain>.TakeTip). After selecting the tip terminal is sending that info as a request (<domain>.TipInfo) to the server and expects instructions on how to process the signature (<domain>.TakeSignature). So as you see each response is meant to be on a separate, and specific subject which is different from the subject which initialized the request. We need a control over on what subject we will receive the response. Currently we use our own implementation of a request() (in the code I presented as a working solution) which does the trick but because of Message.replyTo field (which as you said is a bit misleading) I thought that I could finally use your request() which would definitely simplify our unit tests. It would be great if you could enhance your SDK with such a functionality.

@scottf
Copy link
Contributor

scottf commented Apr 7, 2021

@malloth We have reviewed this request and realized that request must remain as it. The request is intending for the sender to receive a reply,, not for another consumer to receive that reply. But I think there are other ways to solve your use case, leveraging wildcard subjects. I built an example for you to look at here: https://github.com/nats-io/java-nats-examples/tree/main/chain-of-command

@scottf
Copy link
Contributor

scottf commented Apr 30, 2021

This is documented in the upcoming release.

Reply To When Making A Request

The Message object allows you to set a replyTo, but in requests, the replyTo is reserved for internal use as the address for the server to respond to the client with the consumer's reply.

Reply To When Publishing

The Message object allows you to set a replyTo, but in publish requests, the replyTo is reserved for internal use as the address for the server to respond to the client with the PublishAck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants