public async Task Client_Should_be_able_to_publish_and_consume_messages_When_publishing_one_by_one() { var subject = Context.GenerateSubject(); var messages = new[] { "My test string\r\nwith two lines and\ttabs!", "Foo bar!", "My async test string\r\nwith two lines and\ttabs!", "Async Foo bar!" }; _sync = Sync.Max(4); _client1 = await Context.ConnectClientAsync(); _client1.MsgOpStream.Subscribe(msg => _sync.Release(msg)); _client1.Sub(subject); await Context.DelayAsync(); _client1.Pub(subject, messages[0]); _client1.Pub(subject, Encoding.UTF8.GetBytes(messages[1])); await _client1.PubAsync(subject, messages[2]); await _client1.PubAsync(subject, Encoding.UTF8.GetBytes(messages[3])); _sync.WaitForAll(); _sync.InterceptedCount.Should().Be(messages.Length); _sync.Intercepted.Select(m => m.GetPayloadAsString()).ToArray().Should().Contain(messages); }
public async Task Given_responder_exists_When_requesting_using_string_It_should_get_response() { var value = Guid.NewGuid().ToString("N"); _responder.Sub("getValue", stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString()))); var response = await _requester.RequestAsync("getValue", value); response.GetPayloadAsString().Should().Be(value); }
public async Task Client_Should_throw_if_pub_after_disconnected() { var subject = Context.GenerateSubject(); var body = new byte[0]; _client1 = await Context.ConnectClientAsync(); // Succeeds _client1.Pub(subject, "body"); _client1.Pub(subject, "body", "repy.to.subject"); _client1.Pub(subject, body.AsMemory()); _client1.Pub(subject, body.AsMemory(), "repy.to.subject"); // Disconnect from NATS per user request _client1.Disconnect(); Assert.False(_client1.IsConnected); // Fails after being disconnected Should.ThrowNatsException(() => _client1.Pub(subject, "body")); Should.ThrowNatsException(() => _client1.Pub(subject, "body", "reply.to.subject")); Should.ThrowNatsException(() => _client1.Pub(subject, body.AsMemory())); Should.ThrowNatsException(() => _client1.Pub(subject, body.AsMemory(), "reply.to.subject")); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, "body")); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, "body", "reply.to.subject")); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, body.AsMemory())); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, body.AsMemory(), "reply.to.subject")); }
public async Task Given_multiple_responders_exists_When_requesting_It_should_return_one_response() { var value = Guid.NewGuid().ToString("N"); var responderReplyingCount = 0; var responderReplyCount = 0; _requester.MsgOpStream.Subscribe(msgOp => Interlocked.Increment(ref responderReplyCount)); _responder.Sub("getValue", stream => stream.Subscribe(msg => { Interlocked.Increment(ref responderReplyingCount); _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString()); })); MsgOp response; using (var responder2 = new NatsClient(ConnectionInfo)) { responder2.Connect(); responder2.Sub("getValue", stream => stream.Subscribe(msg => { Interlocked.Increment(ref responderReplyingCount); responder2.Pub(msg.ReplyTo, msg.GetPayloadAsString()); })); response = await _requester.RequestAsync("getValue", value); } response.GetPayloadAsString().Should().Be(value); responderReplyCount.Should().Be(1); responderReplyingCount.Should().Be(2); }
public async Task Client_Should_be_able_to_publish_When_no_subscribers_exists() { _client1 = await Context.ConnectClientAsync(); _client1.Pub("Test", "test message"); await _client1.PubAsync("Test", "Test message"); }
/// <summary> /// Starts the subscription /// </summary> /// <summary> /// Starts the subscription /// </summary> public async Task Start() { if (_disposed) { throw new ObjectDisposedException($"{typeof(JsonRpcSubscription).FullName}@{this.GetHashCode()}"); } if (!_client.IsConnected) { _client.Connect(); } if (_subscription != null) { await _client.UnsubAsync(_subscription); _subscription = null; } _subscription = await _client.SubAsync(_sInfo, stream => stream.Subscribe(msg => { try { byte[] resp = OnMessage(msg.Payload); _client.Pub(msg.ReplyTo, resp); } catch (Exception ex) { _logger?.LogError(ex, "Error publishing NATS message"); } }, error => { _logger?.LogError(error, "Fatal error in NATS subscription handler"); })); }
public async Task Client_Should_throw_if_request_after_disconnected() { var subject = Context.GenerateSubject(); var body = new byte[0]; _responder = await Context.ConnectClientAsync(); _requester = await Context.ConnectClientAsync(); _responder.Sub(subject, stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString()))); await Context.DelayAsync(); // Succeeds var response = await _requester.RequestAsync(subject, "body"); Assert.NotNull(response); response = await _requester.RequestAsync(subject, body.AsMemory()); Assert.NotNull(response); // Disconnect from NATS per user request _requester.Disconnect(); Assert.False(_requester.IsConnected); // Fails after being disconnected await Should.ThrowNatsExceptionAsync(() => _requester.RequestAsync(subject, "body")); await Should.ThrowNatsExceptionAsync(() => _requester.RequestAsync(subject, body.AsMemory())); }
public async Task Client_Should_be_able_to_unsub_from_a_subject() { var subject = Context.GenerateSubject(); var nr1Received = new ConcurrentQueue <MsgOp>(); var nr2Received = new ConcurrentQueue <MsgOp>(); var nr3Received = new ConcurrentQueue <MsgOp>(); var subInfo1 = new SubscriptionInfo(subject); var subInfo2 = new SubscriptionInfo(subject); var subInfo3 = new SubscriptionInfo(subject); _sync = Sync.MaxThree(); await ConnectAllClients(); _client1.OpStream.OfType <MsgOp>().Subscribe(msg => { _client1.Unsub(subInfo1); nr1Received.Enqueue(msg); _sync.Release(msg); }); _client1.Sub(subInfo1); _client2.OpStream.OfType <MsgOp>().Subscribe(async msg => { await _client2.UnsubAsync(subInfo2); nr2Received.Enqueue(msg); _sync.Release(msg); }); _client2.Sub(subInfo2); _client3.OpStream.OfType <MsgOp>().Subscribe(msg => { nr3Received.Enqueue(msg); _sync.Release(msg); }); _client3.Sub(subInfo3); await Context.DelayAsync(); _client1.Pub(subject, "mess1"); _sync.WaitForAll(); _client3.Unsub(subInfo3); await Context.DelayAsync(); _client1.Pub(subject, "mess2"); await Context.DelayAsync(); _sync.InterceptedCount.Should().Be(3); nr1Received.Should().HaveCount(1); nr2Received.Should().HaveCount(1); nr3Received.Should().HaveCount(1); }
public async Task Client_Should_be_able_to_unsub_from_a_subject() { const string subject = "Test"; var nr1ReceiveCount = 0; var nr2ReceiveCount = 0; var nr3ReceiveCount = 0; var subInfo1 = new SubscriptionInfo(subject); var subInfo2 = new SubscriptionInfo(subject); var subInfo3 = new SubscriptionInfo(subject); _client1.OpStream.OfType <MsgOp>().Subscribe(msg => { _client1.Unsub(subInfo1); Interlocked.Increment(ref nr1ReceiveCount); ReleaseOne(); }); _client1.Sub(subInfo1); _client2.OpStream.OfType <MsgOp>().Subscribe(async msg => { await _client2.UnsubAsync(subInfo2); Interlocked.Increment(ref nr2ReceiveCount); ReleaseOne(); }); _client2.Sub(subInfo2); _client3.OpStream.OfType <MsgOp>().Subscribe(msg => { Interlocked.Increment(ref nr3ReceiveCount); ReleaseOne(); }); _client3.Sub(subInfo3); _client1.Pub(subject, "mess1"); WaitOne(); WaitOne(); WaitOne(); _client3.Unsub(subInfo3); await DelayAsync(); _client1.Pub(subject, "mess2"); await DelayAsync(); nr1ReceiveCount.Should().Be(1); nr2ReceiveCount.Should().Be(1); nr3ReceiveCount.Should().Be(1); }
public async Task Client_Should_throw_if_pub_when_never_connected() { var subject = Context.GenerateSubject(); var body = new byte[0]; _client1 = Context.CreateClient(); Should.ThrowNatsException(() => _client1.Pub(subject, "body")); Should.ThrowNatsException(() => _client1.Pub(subject, "body", "reply.to.subject")); Should.ThrowNatsException(() => _client1.Pub(subject, body.AsMemory())); Should.ThrowNatsException(() => _client1.Pub(subject, body.AsMemory(), "reply.to.subject")); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, "body")); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, "body", "reply.to.subject")); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, body.AsMemory())); await Should.ThrowNatsExceptionAsync(() => _client1.PubAsync(subject, body.AsMemory(), "reply.to.subject")); }
public async Task Client_Should_be_able_to_subscribe_to_many_subjects() { var subject1 = Context.GenerateSubject(); var subject2 = Context.GenerateSubject(); _sync = Sync.MaxTwo(); _client1 = await Context.ConnectClientAsync(); _client1.OpStream.OfType <MsgOp>().Where(m => m.Subject == subject1).Subscribe(msg => _sync.Release(msg)); _client1.OpStream.OfType <MsgOp>().Where(m => m.Subject == subject2).Subscribe(msg => _sync.Release(msg)); _client1.Sub(subject1); _client1.Sub(subject2); await Context.DelayAsync(); _client1.Pub(subject1, "mess1"); _client1.Pub(subject2, "mess2"); _sync.WaitForAll(); _sync.InterceptedCount.Should().Be(2); }
public async Task Given_multiple_responders_exists_and_non_inbox_requests_are_used_When_requesting_It_should_call_requester_once_and_dispatch_one_response() { _sync = Sync.MaxTwo(); var cnInfoResponder = Context.GetConnectionInfo(); var cnInfoRequester = cnInfoResponder.Clone(); cnInfoRequester.UseInboxRequests = false; var value = Guid.NewGuid().ToString("N"); var responderReceived = new ConcurrentQueue <MsgOp>(); var requesterReceived = new ConcurrentQueue <MsgOp>(); var responsesReceived = new ConcurrentQueue <MsgOp>(); _responder = await Context.ConnectClientAsync(cnInfoResponder); _requester = await Context.ConnectClientAsync(cnInfoRequester); _requester.MsgOpStream.Subscribe(msgOp => requesterReceived.Enqueue(msgOp)); _responder.Sub("getValue", stream => stream.Subscribe(msg => { responderReceived.Enqueue(msg); _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString()); _sync.Release(); })); using (var responder2 = new NatsClient(cnInfoResponder)) { await responder2.ConnectAsync(); responder2.Sub("getValue", stream => stream.Subscribe(msg => { responderReceived.Enqueue(msg); responder2.Pub(msg.ReplyTo, msg.GetPayloadAsString()); _sync.Release(); })); await Context.DelayAsync(); var response = await _requester.RequestAsync("getValue", value); responsesReceived.Enqueue(response); } _sync.WaitForAll(); responsesReceived.Should().HaveCount(1); requesterReceived.Should().HaveCount(1); responderReceived.Should().HaveCount(2); responsesReceived.First().GetPayloadAsString().Should().Be(value); }
public async Task Given_responder_exists_When_requesting_using_bytes_It_should_get_response() { var value = Guid.NewGuid().ToString("N"); _responder = await Context.ConnectClientAsync(); _requester = await Context.ConnectClientAsync(); _responder.Sub("getValue", stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString()))); await Context.DelayAsync(); var response = await _requester.RequestAsync("getValue", Encoding.UTF8.GetBytes(value)); response.GetPayloadAsString().Should().Be(value); }
public async Task Client_Should_be_able_to_publish_to_it_self() { var subject = Context.GenerateSubject(); _sync = Sync.MaxOne(); _client1 = await Context.ConnectClientAsync(); _client1.OpStream.OfType <MsgOp>().Subscribe(msg => _sync.Release(msg)); _client1.Sub(subject); await Context.DelayAsync(); _client1.Pub(subject, "mess1"); _sync.WaitForAll(); _sync.InterceptedCount.Should().Be(1); }
static async Task Main(string[] args) { Console.WriteLine("Hello World!"); // hit ctrl-C to close/exit var cts = new CancellationTokenSource(); Console.CancelKeyPress += (_, e) => { Console.WriteLine("cancelled..."); cts.Cancel(); e.Cancel = true; }; var sp = ConfigureServices(); var client = new ClientBuilder(sp) .UseSockets() //.UseConnectionLogging() .Build(); var conn = await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 4222)); var nats = new NatsClient(); await nats.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 4222), sp); // test this with "pub test2 2\r\nhi" from telnet nats.Sub("test2", "1", msg => { var text = Encoding.UTF8.GetString(msg.Data.Span); Console.WriteLine($"OnMsg: subject:{msg.Subject} sid:{msg.Sid} replyto:{msg.ReplyTo} text:{text}"); }); // test this with "sub test1 1" from telnet while (!cts.Token.IsCancellationRequested) { Console.WriteLine("pub..."); nats.Pub("test1", Encoding.UTF8.GetBytes("hello")); await Task.Delay(2000); } Console.WriteLine("done..."); Console.ReadLine(); }
public async Task Given_responder_exists_When_requesting_using_string_It_should_get_response() { var value = Guid.NewGuid().ToString("N"); var connectionInfo = Context .GetConnectionInfo() .AllowAllServerCertificates(); _responder = await Context.ConnectClientAsync(connectionInfo); _requester = await Context.ConnectClientAsync(connectionInfo); _responder.Sub("getValue", stream => stream.Subscribe(msg => _responder.Pub(msg.ReplyTo, msg.GetPayloadAsString()))); var response = await _requester.RequestAsync("getValue", value); response.GetPayloadAsString().Should().Be(value); }
public async Task Client_Should_dispatch_to_all_subscribed_clients() { var subject = Context.GenerateSubject(); var nr1Receive = new ConcurrentQueue <MsgOp>(); var nr2Receive = new ConcurrentQueue <MsgOp>(); var nr3Receive = new ConcurrentQueue <MsgOp>(); _sync = Sync.MaxTwo(); _client1 = await Context.ConnectClientAsync(); _client2 = await Context.ConnectClientAsync(); _client3 = await Context.ConnectClientAsync(); _client1.OpStream.OfType <MsgOp>().Subscribe(msg => nr1Receive.Enqueue(msg)); _client2.OpStream.OfType <MsgOp>().Subscribe(msg => { nr2Receive.Enqueue(msg); _sync.Release(msg); }); _client2.Sub(subject); _client3.OpStream.OfType <MsgOp>().Subscribe(msg => { nr3Receive.Enqueue(msg); _sync.Release(msg); }); await _client3.SubAsync(subject); await Context.DelayAsync(); _client1.Pub(subject, "mess1"); _sync.WaitForAll(); await _client1.PubAsync(subject, "mess2"); _sync.WaitForAll(); _sync.InterceptedCount.Should().Be(4); nr1Receive.Count.Should().Be(0); nr2Receive.Count.Should().Be(2); nr3Receive.Count.Should().Be(2); }
public static async Task RunAsync(ConnectionInfo cnInfo) { using (var client = new NatsClient("Sample7", cnInfo)) { client.Connect(); //Respond to request's "replyTo" await client.SubWithHandlerAsync( "demo-request", msgOp => { var msg = msgOp.GetPayloadAsString(); Console.WriteLine($"I got request: {msg}"); client.Pub(msgOp.ReplyTo, $"You requested: {msg}"); }); Console.WriteLine("Hit key to quit."); Console.ReadKey(); } }
public static async Task <TimeSpan> MyNatsClientRequestAsync(int n, ReadOnlyMemory <byte> payload, bool useTls) { Console.WriteLine($"MyNatsClient-RequestAsync: n={n} s={payload.Length}"); const string subject = "casea"; using var cts = new CancellationTokenSource(); using var sync = new AutoResetEvent(false); var tcs = new TaskCompletionSource <TimeSpan>(); var cnInfo = new ConnectionInfo("127.0.0.1"); if (useTls) { cnInfo.ServerCertificateValidation = (_, __, ___) => true; } var responderTask = Task.Factory.StartNew(async() => { using var client = new NatsClient(cnInfo); await client.ConnectAsync().ConfigureAwait(false); client.Sub(subject, messages => messages.SubscribeSafe(msg => { client.Pub(msg.ReplyTo, msg.Payload); })); sync.Set(); await tcs.Task.ConfigureAwait(false); }, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); var requesterTask = Task.Factory.StartNew(async() => { using var client = new NatsClient(cnInfo); await client.ConnectAsync().ConfigureAwait(false); if (!sync.WaitOne(1000)) { throw new Exception("Responder does not seem to be started."); } for (var i = 0; i < 10; i++) { await client.RequestAsync(subject, payload, cts.Token).ConfigureAwait(false); } var sw = Stopwatch.StartNew(); for (var i = 0; i < n; i++) { await client.RequestAsync(subject, payload, cts.Token).ConfigureAwait(false); } sw.Stop(); tcs.SetResult(sw.Elapsed); }, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); var elapsed = await tcs.Task.ConfigureAwait(false); cts.Cancel(); await Task.WhenAll(responderTask, requesterTask).ConfigureAwait(false); return(elapsed); }