diff --git a/src/NATS.Client.Core/INatsConnection.cs b/src/NATS.Client.Core/INatsConnection.cs index f7931d43e..f83a49580 100644 --- a/src/NATS.Client.Core/INatsConnection.cs +++ b/src/NATS.Client.Core/INatsConnection.cs @@ -131,7 +131,7 @@ public interface INatsConnection : IAsyncDisposable /// /// Response can be (null) or one . /// Reply option's max messages will be set to 1. - /// if reply option's timeout is not defined then it will be set to NatsOpts.RequestTimeout. + /// If reply option's timeout is not defined, then it will be set to NatsOpts.RequestTimeout. /// ValueTask> RequestAsync( string subject, @@ -143,6 +143,27 @@ ValueTask> RequestAsync( NatsSubOpts? replyOpts = default, CancellationToken cancellationToken = default); + /// + /// Send an empty request message and await the reply message asynchronously. + /// + /// Subject of the responder + /// Serializer to use for the reply message type. + /// Reply handler subscription options + /// Cancel this request + /// Reply type + /// Returns the received from the responder as reply. + /// Raised when cancellation token is used + /// + /// Response can be (null) or one . + /// Reply option's max messages will be set to 1. + /// If reply option's timeout is not defined, then it will be set to NatsOpts.RequestTimeout. + /// + ValueTask> RequestAsync( + string subject, + INatsDeserialize? replySerializer = default, + NatsSubOpts? replyOpts = default, + CancellationToken cancellationToken = default); + /// /// Request and receive zero or more replies from a responder. /// diff --git a/src/NATS.Client.Core/NatsConnection.RequestReply.cs b/src/NATS.Client.Core/NatsConnection.RequestReply.cs index 76a3d1b0c..766c93522 100644 --- a/src/NATS.Client.Core/NatsConnection.RequestReply.cs +++ b/src/NATS.Client.Core/NatsConnection.RequestReply.cs @@ -74,6 +74,22 @@ public async ValueTask> RequestAsync( throw new NatsNoReplyException(); } + /// + public ValueTask> RequestAsync( + string subject, + INatsDeserialize? replySerializer = default, + NatsSubOpts? replyOpts = default, + CancellationToken cancellationToken = default) => + RequestAsync( + subject: subject, + data: default, + headers: default, + requestSerializer: default, + replySerializer: replySerializer, + requestOpts: default, + replyOpts: replyOpts, + cancellationToken: cancellationToken); + /// public async IAsyncEnumerable> RequestManyAsync( string subject, diff --git a/tests/NATS.Client.Core.Tests/RequestReplyTest.cs b/tests/NATS.Client.Core.Tests/RequestReplyTest.cs index 9bcc86b3c..83846cdf5 100644 --- a/tests/NATS.Client.Core.Tests/RequestReplyTest.cs +++ b/tests/NATS.Client.Core.Tests/RequestReplyTest.cs @@ -392,4 +392,30 @@ public async Task Request_reply_many_multiple_with_timeout_test() await sub.DisposeAsync(); await reg; } + + [Fact] + public async Task Simple_empty_request_reply_test() + { + await using var server = NatsServer.Start(); + await using var nats = server.CreateClientConnection(); + + const string subject = "foo"; + var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var cancellationToken = cts.Token; + + var sub = await nats.SubscribeCoreAsync(subject, cancellationToken: cancellationToken); + var reg = sub.Register(async msg => + { + await msg.ReplyAsync(42, cancellationToken: cancellationToken); + }); + + var reply1 = await nats.RequestAsync(subject, null, cancellationToken: cancellationToken); + var reply2 = await nats.RequestAsync(subject, cancellationToken: cancellationToken); + + Assert.Equal(42, reply1.Data); + Assert.Equal(42, reply2.Data); + + await sub.DisposeAsync(); + await reg; + } } diff --git a/tests/NATS.Client.JetStream.Tests/NatsJsContextFactoryTest.cs b/tests/NATS.Client.JetStream.Tests/NatsJsContextFactoryTest.cs index b7562bebf..c70453892 100644 --- a/tests/NATS.Client.JetStream.Tests/NatsJsContextFactoryTest.cs +++ b/tests/NATS.Client.JetStream.Tests/NatsJsContextFactoryTest.cs @@ -123,6 +123,8 @@ public ValueTask> RequestAsync( CancellationToken cancellationToken = default) => throw new NotImplementedException(); + public ValueTask> RequestAsync(string subject, INatsDeserialize? replySerializer = default, NatsSubOpts? replyOpts = default, CancellationToken cancellationToken = default) => throw new NotImplementedException(); + public IAsyncEnumerable> RequestManyAsync( string subject, TRequest? data,