nats-io / nats.deno

Deno client for NATS, the cloud native messaging system
https://www.nats.io
Apache License 2.0
159 stars 50 forks source link

Publish with No-Responder #730

Open Zetanova opened 1 week ago

Zetanova commented 1 week ago

Proposed change

there is currently no positionality to publish a request on a custom reply subject and provide the same behavior like over request method with a fast failure with No responders are available.

a methoth like nc.publishMessageAck(msg:Msg): Promise<Pick<MsgHdrs, 'hasError','status','code','description'>> is missing

Use case

I need/want to use a custom replay subscription and utilize the nats no-responders feature.

Contribution

No response

Jarema commented 1 week ago

NATS request is just a publish with provided reply subject.

If you want to manually use request-reply pattern with your own subjects, you can simply:

  // Subscribe to "responses" subject
  const sub = nc.subscribe("responses");

 // Process messages from the "responses" subject
   ...

  // Publish a message to "requests" subject with a reply to "responses"
  nc.publish("requests", "Hello, World!", {
    reply: "responses",
  });
Zetanova commented 1 week ago

@Jarema This is well known and working fine. The no-responders feature is over the ack response packet (If I am not mistaken) Even with the nats-cli it does only work with a direct req command and not with pub/sub

Jarema commented 1 week ago

no responders is an error message send back on reply subject. I'm not sure why cli does not show it if you do it manually - maybe it disconnects before that happens, but it happens for sure.

Using Rust example:

use futures::StreamExt;

#[tokio::main]
async fn main() {
    let client = async_nats::connect("localhost:4222").await.unwrap();

    let mut responses = client.subscribe("hello").await.unwrap();

    client
        .publish_with_reply("foo", "hello", "data".into())
        .await
        .unwrap();

    println!("{:?}", responses.next().await.unwrap());
}

prints out:

Message { subject: Subject { bytes: b"hello" }, reply: None, payload: b"", headers: Some(HeaderMap { inner: {} }), status: Some(503), description: None, length: 21 }

Which is exactly the no responders (503 status). The only question is if the deno client shows the error status messages to the user, but @aricart can definately answer and help here 🙂

Zetanova commented 1 week ago

Thanks for testing, tried again with nats-cli

$ nats sub "test.reply.>"
$ nats pub "test.service" --reply "test.reply.A" ""

It simply does not work for me, maybe because I am still on an older nats server v2.9.

Zetanova commented 1 week ago

maybe the client is ignoring the error message on a custom subscription?

Jarema commented 1 week ago

Figured it out - you do not see the 503 message on nats sub, because no responders are sent only if the subscription for reply is on the same client connection where the publish with reply was sent from. Meanwhile each nats cli command creates a new connection.

Zetanova commented 1 week ago

Great, one mystery solved.

Is this the same reason why no-responders feature does not work with account import/export service? see issue

The nats behavior seams a bit off, in osi model the last router/server should respond with the routing/forward error