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);
        }
Beispiel #2
0
        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"));
        }
Beispiel #4
0
        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");
            }));
        }
Beispiel #7
0
        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()));
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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"));
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        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();
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        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();
            }
        }
Beispiel #19
0
        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);
        }