Example #1
0
        public void TestJetStreamPushEphemeral(string deliverSubject)
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                // publish some messages
                JsPublish(js, SUBJECT, 1, 5);

                // Build our subscription options.
                PushSubscribeOptions options = PushSubscribeOptions.Builder()
                                               .WithDeliverSubject(deliverSubject)
                                               .Build();

                // Subscription 1
                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT, options);
                AssertSubscription(sub, STREAM, null, deliverSubject, false);
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server

                IList <Msg> messages1 = ReadMessagesAck(sub);
                int total             = messages1.Count;
                ValidateRedAndTotal(5, messages1.Count, 5, total);

                // read again, nothing should be there
                IList <Msg> messages0 = ReadMessagesAck(sub);
                total += messages0.Count;
                ValidateRedAndTotal(0, messages0.Count, 5, total);

                sub.Unsubscribe();

                // Subscription 2
                sub = js.PushSubscribeSync(SUBJECT, options);
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server

                // read what is available, same messages
                IList <Msg> messages2 = ReadMessagesAck(sub);
                total = messages2.Count;
                ValidateRedAndTotal(5, messages2.Count, 5, total);

                // read again, nothing should be there
                messages0 = ReadMessagesAck(sub);
                total    += messages0.Count;
                ValidateRedAndTotal(0, messages0.Count, 5, total);

                AssertSameMessages(messages1, messages2);
            });
        }
Example #2
0
        public void TestBindDurableDeliverSubject()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);

                IJetStream js            = c.CreateJetStreamContext();
                IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                // create a durable push subscriber - has deliver subject
                ConsumerConfiguration ccDurPush = ConsumerConfiguration.Builder()
                                                  .WithDurable(Durable(1))
                                                  .WithDeliverSubject(Deliver(1))
                                                  .Build();
                jsm.AddOrUpdateConsumer(STREAM, ccDurPush);

                // create a durable pull subscriber - notice no deliver subject
                ConsumerConfiguration ccDurPull = ConsumerConfiguration.Builder()
                                                  .WithDurable(Durable(2))
                                                  .Build();
                jsm.AddOrUpdateConsumer(STREAM, ccDurPull);

                // try to pull subscribe against a push durable
                NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(
                    () => js.PullSubscribe(SUBJECT, PullSubscribeOptions.Builder().WithDurable(Durable(1)).Build()));
                Assert.Contains(JsSubConsumerAlreadyConfiguredAsPush.Id, e.Message);

                // try to pull bind against a push durable
                e = Assert.Throws <NATSJetStreamClientException>(
                    () => js.PullSubscribe(SUBJECT, PullSubscribeOptions.BindTo(STREAM, Durable(1))));
                Assert.Contains(JsSubConsumerAlreadyConfiguredAsPush.Id, e.Message);

                // this one is okay
                IJetStreamPullSubscription sub = js.PullSubscribe(SUBJECT, PullSubscribeOptions.Builder().WithDurable(Durable(2)).Build());
                sub.Unsubscribe(); // so I can re-use the durable

                // try to push subscribe against a pull durable
                e = Assert.Throws <NATSJetStreamClientException>(
                    () => js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.Builder().WithDurable(Durable(2)).Build()));
                Assert.Contains(JsSubConsumerAlreadyConfiguredAsPull.Id, e.Message);

                // try to push bind against a pull durable
                e = Assert.Throws <NATSJetStreamClientException>(
                    () => js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.BindTo(STREAM, Durable(2))));
                Assert.Contains(JsSubConsumerAlreadyConfiguredAsPull.Id, e.Message);

                // this one is okay
                js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.Builder().WithDurable(Durable(1)).Build());
            });
        }
Example #3
0
        private void SubscribeOk(IJetStream js, IJetStreamManagement jsm, string fs, string ss)
        {
            int i = Rndm.Next(); // just want a unique number

            SetupConsumer(jsm, i, fs);
            js.PushSubscribeSync(ss, ConsumerConfiguration.Builder().WithDurable(Durable(i)).BuildPushSubscribeOptions()).Unsubscribe();
        }
Example #4
0
        public void TestQueueSubWorkflow()
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                // Setup the subscribers
                // - the PushSubscribeOptions can be re-used since all the subscribers are the same
                // - use a concurrent integer to track all the messages received
                // - have a list of subscribers and threads so I can track them
                PushSubscribeOptions pso              = PushSubscribeOptions.Builder().WithDurable(DURABLE).Build();
                InterlockedLong allReceived           = new InterlockedLong();
                IList <JsQueueSubscriber> subscribers = new List <JsQueueSubscriber>();
                IList <Thread> subThreads             = new List <Thread>();
                for (int id = 1; id <= 3; id++)
                {
                    // setup the subscription
                    IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT, QUEUE, pso);
                    // create and track the runnable
                    JsQueueSubscriber qs = new JsQueueSubscriber(100, js, sub, allReceived);
                    subscribers.Add(qs);
                    // create, track and start the thread
                    Thread t = new Thread(qs.Run);
                    subThreads.Add(t);
                    t.Start();
                }
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server

                // create and start the publishing
                Thread pubThread = new Thread(new JsPublisher(js, 100).Run);
                pubThread.Start();

                // wait for all threads to finish
                pubThread.Join(5000);
                foreach (Thread t in subThreads)
                {
                    t.Join(5000);
                }

                ISet <string> uniqueDatas = new HashSet <string>();
                // count
                int count = 0;
                foreach (JsQueueSubscriber qs in subscribers)
                {
                    int r = qs.received;
                    Assert.True(r > 0);
                    count += r;
                    foreach (string s in qs.datas)
                    {
                        Assert.True(uniqueDatas.Add(s));
                    }
                }

                Assert.Equal(100, count);
            });
        }
        public void TestPublishNoAck()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);

                JetStreamOptions jso = JetStreamOptions.Builder().WithPublishNoAck(true).Build();
                IJetStream js        = c.CreateJetStreamContext(jso);

                string data1 = "noackdata1";
                string data2 = "noackdata2";

                PublishAck pa = js.Publish(SUBJECT, Encoding.ASCII.GetBytes(data1));
                Assert.Null(pa);

                Task <PublishAck> task = js.PublishAsync(SUBJECT, Encoding.ASCII.GetBytes(data2));
                Assert.Null(task.Result);

                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT);
                Msg m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal(data1, Encoding.ASCII.GetString(m.Data));
                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal(data2, Encoding.ASCII.GetString(m.Data));
            });
        }
Example #6
0
        private void ChangeExPush(IJetStream js, ConsumerConfiguration.ConsumerConfigurationBuilder builder, String changedField)
        {
            NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(
                () => js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.Builder().WithConfiguration(builder.Build()).Build()));

            _ChangeEx(e, changedField);
        }
Example #7
0
        public void TestJetStreamPushDurableSubSync()
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js            = c.CreateJetStreamContext();
                IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                // publish some messages
                JsPublish(js, SUBJECT, 1, 5);

                // Build our subscription options normally
                PushSubscribeOptions optionsSync1 = PushSubscribeOptions.Builder()
                                                    .WithDurable(Durable(1))
                                                    .WithDeliverSubject(Deliver(1))
                                                    .Build();
                _testPushDurableSubSync(Durable(1), Deliver(1), c, () => js.PushSubscribeSync(SUBJECT, optionsSync1));

                // bind long form
                jsm.AddOrUpdateConsumer(STREAM,
                                        ConsumerConfiguration.Builder()
                                        .WithDurable(Durable(2))
                                        .WithDeliverSubject(Deliver(2))
                                        .Build());
                PushSubscribeOptions options2 = PushSubscribeOptions.Builder()
                                                .WithStream(STREAM)
                                                .WithDurable(Durable(2))
                                                .WithBind(true)
                                                .Build();
                _testPushDurableSubSync(Durable(2), Deliver(2), c, () => js.PushSubscribeSync(null, options2));

                // bind short form
                jsm.AddOrUpdateConsumer(STREAM,
                                        ConsumerConfiguration.Builder()
                                        .WithDurable(Durable(3))
                                        .WithDeliverSubject(Deliver(3))
                                        .Build());
                PushSubscribeOptions options3 = PushSubscribeOptions.BindTo(STREAM, Durable(3));
                _testPushDurableSubSync(Durable(3), Deliver(3), c, () => js.PushSubscribeSync(null, options3));
            });
        }
Example #8
0
        private void SubscribeEx(IJetStream js, IJetStreamManagement jsm, string fs, string ss)
        {
            int i = Rndm.Next(); // just want a unique number

            SetupConsumer(jsm, i, fs);
            NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(
                () => js.PushSubscribeSync(ss, ConsumerConfiguration.Builder().WithDurable(Durable(i)).BuildPushSubscribeOptions()));

            Assert.Contains(JsSubSubjectDoesNotMatchFilter.Id, e.Message);
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("JetStream Publish Vs Core Publish", args, Usage)
                                    .DefaultStream("js-or-core-stream")
                                    .DefaultSubject("js-or-core-subject")
                                    .Build();

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // Create a JetStreamManagement context.
                    IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                    // Use the utility to create a stream stored in memory.
                    JsUtils.CreateStreamExitWhenExists(jsm, helper.Stream, helper.Subject);

                    // create a JetStream context
                    IJetStream js = c.CreateJetStreamContext();

                    // Regular Nats publish is straightforward
                    c.Publish(helper.Subject, Encoding.ASCII.GetBytes("regular-message"));

                    // A JetStream publish allows you to set publish options
                    // that a regular publish does not.
                    // A JetStream publish returns an ack of the publish. There
                    // is no ack in a regular message.
                    Msg msg = new Msg(helper.Subject, Encoding.ASCII.GetBytes("js-message"));

                    PublishAck pa = js.Publish(msg);
                    Console.WriteLine(pa);

                    // set up the subscription
                    IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(helper.Subject);
                    c.Flush(500); // flush outgoing communication with/to the server

                    // Both messages appear in the stream as JetStream messages
                    msg = sub.NextMessage(500);
                    msg.Ack();
                    Console.WriteLine("Received Data: '" + Encoding.ASCII.GetString(msg.Data) + "'\n         Meta: " + msg.MetaData);

                    msg = sub.NextMessage(500);
                    msg.Ack();
                    Console.WriteLine("Received Data: '" + Encoding.ASCII.GetString(msg.Data) + "'\n         Meta: " + msg.MetaData);

                    // delete the stream since we are done with it.
                    jsm.DeleteStream(helper.Stream);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Example #10
0
        public void TestPushSyncFlowControl()
        {
            InterlockedInt fcps = new InterlockedInt();

            Action <Options> optionsModifier = opts =>
            {
                opts.FlowControlProcessedEventHandler = (sender, args) => { fcps.Increment(); };
            };

            Context.RunInJsServer(new TestServerInfo(TestSeedPorts.AutoPort.Increment()), optionsModifier, c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                byte[] data = new byte[8192];

                int MSG_COUNT = 1000;

                for (int x = 100_000; x < MSG_COUNT + 100_000; x++)
                {
                    byte[] fill = Encoding.ASCII.GetBytes("" + x);
                    Array.Copy(fill, 0, data, 0, 6);
                    js.Publish(new Msg(SUBJECT, data));
                }

                InterlockedInt count = new InterlockedInt();
                HashSet <string> set = new HashSet <string>();

                ConsumerConfiguration cc = ConsumerConfiguration.Builder().WithFlowControl(1000).Build();
                PushSubscribeOptions pso = PushSubscribeOptions.Builder().WithConfiguration(cc).Build();

                IJetStreamPushSyncSubscription ssub = js.PushSubscribeSync(SUBJECT, pso);
                for (int x = 0; x < MSG_COUNT; x++)
                {
                    Msg msg     = ssub.NextMessage(1000);
                    byte[] fill = new byte[6];
                    Array.Copy(msg.Data, 0, fill, 0, 6);
                    string id = Encoding.ASCII.GetString(fill);
                    if (set.Add(id))
                    {
                        count.Increment();
                    }

                    msg.Ack();
                }

                Assert.Equal(MSG_COUNT, count.Read());
                Assert.True(fcps.Read() > 0);
            });
        }
Example #11
0
        public void TestMessageWithHeadersOnly()
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                MsgHeader h = new MsgHeader();
                h["foo"]    = "bar";
                js.Publish(new Msg(SUBJECT, h, DataBytes(1)));

                // Build our subscription options.
                PushSubscribeOptions options = ConsumerConfiguration.Builder()
                                               .WithHeadersOnly(true).BuildPushSubscribeOptions();

                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT, options);
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server

                Msg m = sub.NextMessage(1000);
                Assert.Empty(m.Data);
                Assert.True(m.HasHeaders);
                Assert.Equal("bar", m.Header["foo"]);
                Assert.Equal("6", m.Header[JetStreamConstants.MsgSizeHeader]);

                sub.Unsubscribe();

                // without headers only
                sub = js.PushSubscribeSync(SUBJECT);
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server
                m = sub.NextMessage(1000);
                Assert.Equal(6, m.Data.Length);
                Assert.True(m.HasHeaders);
                Assert.Equal("bar", m.Header["foo"]);
                Assert.Null(m.Header[JetStreamConstants.MsgSizeHeader]);
            });
        }
Example #12
0
        public void TestPublishVarieties()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);
                IJetStream js = c.CreateJetStreamContext();

                PublishAck pa = js.Publish(SUBJECT, DataBytes(1));
                AssertPublishAck(pa, 1);

                Msg msg = new Msg(SUBJECT, DataBytes(2));
                pa      = js.Publish(msg);
                AssertPublishAck(pa, 2);

                PublishOptions po = PublishOptions.Builder().Build();
                pa = js.Publish(SUBJECT, DataBytes(3), po);
                AssertPublishAck(pa, 3);

                msg = new Msg(SUBJECT, DataBytes(4));
                pa  = js.Publish(msg, po);
                AssertPublishAck(pa, 4);

                pa = js.Publish(SUBJECT, null);
                AssertPublishAck(pa, 5);

                msg = new Msg(SUBJECT);
                pa  = js.Publish(msg);
                AssertPublishAck(pa, 6);

                pa = js.Publish(SUBJECT, null, po);
                AssertPublishAck(pa, 7);

                msg = new Msg(SUBJECT);
                pa  = js.Publish(msg, po);
                AssertPublishAck(pa, 8);

                IJetStreamPushSyncSubscription s = js.PushSubscribeSync(SUBJECT);
                AssertNextMessage(s, Data(1));
                AssertNextMessage(s, Data(2));
                AssertNextMessage(s, Data(3));
                AssertNextMessage(s, Data(4));
                AssertNextMessage(s, null); // 5
                AssertNextMessage(s, null); // 6
                AssertNextMessage(s, null); // 7
                AssertNextMessage(s, null); // 8

                // bad subject
                Assert.Throws <NATSNoRespondersException>(() => js.Publish(Subject(999), null));
            });
        }
Example #13
0
        public void TestJetStreamSubscribeErrors()
        {
            Context.RunInJsServer(c =>
            {
                IJetStream js = c.CreateJetStreamContext();

                // stream not found
                PushSubscribeOptions psoInvalidStream = PushSubscribeOptions.Builder().WithStream(STREAM).Build();
                Assert.Throws <NATSJetStreamException>(() => js.PushSubscribeSync(SUBJECT, psoInvalidStream));

                void AssertThrowsForSubject(Func <object> testCode)
                {
                    ArgumentException ae = Assert.Throws <ArgumentException>(testCode);
                    Assert.StartsWith("Subject", ae.Message);
                }

                void AssertThrowsForQueue(Func <object> testCode)
                {
                    ArgumentException ae = Assert.Throws <ArgumentException>(testCode);
                    Assert.StartsWith("Queue", ae.Message);
                }

                void AssertThrowsForHandler(Func <object> testCode)
                {
                    ArgumentNullException ae = Assert.Throws <ArgumentNullException>(testCode);
                    Assert.Equal("Handler", ae.ParamName);
                }

                // subject
                AssertThrowsForSubject(() => js.PushSubscribeSync(HasSpace));
                AssertThrowsForSubject(() => js.PushSubscribeSync(null, (PushSubscribeOptions)null));
                AssertThrowsForSubject(() => js.PushSubscribeSync(HasSpace, Plain));
                AssertThrowsForSubject(() => js.PushSubscribeSync(null, Plain, null));
                AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, null, false));
                AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, null, false, null));
                AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, Plain, null, false));
                AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, Plain, null, false, null));

                // queue
                AssertThrowsForQueue(() => js.PushSubscribeSync(Plain, HasSpace));
                AssertThrowsForQueue(() => js.PushSubscribeSync(Plain, HasSpace, null));
                AssertThrowsForQueue(() => js.PushSubscribeAsync(Plain, HasSpace, null, false));
                AssertThrowsForQueue(() => js.PushSubscribeAsync(Plain, HasSpace, null, false, null));

                // handler
                AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, null, false));
                AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, null, false, null));
                AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, Plain, null, false));
                AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, Plain, null, false, null));
            });
        }
Example #14
0
        public void TestOrderedConsumerSync()
        {
            Console.SetOut(new ConsoleWriter(output));

            Context.RunInJsServer(c =>
            {
                // Setup
                IJetStream js  = c.CreateJetStreamContext();
                string subject = Subject(111);
                CreateMemoryStream(c, Stream(111), subject);

                // Get this in place before any subscriptions are made
                JetStream.PushMessageManagerFactoryImpl =
                    (conn, so, cc, queueMode, syncMode) =>
                    new OrderedTestDropSimulator(conn, so, cc, queueMode, syncMode);

                // The options will be used in various ways
                PushSubscribeOptions pso = PushSubscribeOptions.Builder().WithOrdered(true).Build();

                // Test queue exception
                NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(subject, QUEUE, pso));
                Assert.Contains(JsSubOrderedNotAllowOnQueues.Id, e.Message);

                // Setup sync subscription
                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(subject, pso);
                Thread.Sleep(1000);

                // Published messages will be intercepted by the OrderedTestDropSimulator
                JsPublish(js, subject, 101, 6);

                ulong streamSeq = 1;
                while (streamSeq < 7)
                {
                    Msg m = sub.NextMessage(1000);
                    if (m != null)
                    {
                        Assert.Equal(streamSeq, m.MetaData.StreamSequence);
                        Assert.Equal(ExpectedConSeqNums[streamSeq - 1], m.MetaData.ConsumerSequence);
                        ++streamSeq;
                    }
                }

                sub.Unsubscribe();
                EnsureNotBound(sub);
            });
        }
Example #15
0
        public void TestGetConsumerInfoFromSubscription()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);

                IJetStream js = c.CreateJetStreamContext();

                IJetStreamPushSyncSubscription psync = js.PushSubscribeSync(SUBJECT);
                ConsumerInfo ci = psync.GetConsumerInformation();
                Assert.Equal(STREAM, ci.Stream);

                PullSubscribeOptions pso        = PullSubscribeOptions.Builder().WithDurable(DURABLE).Build();
                IJetStreamPullSubscription pull = js.PullSubscribe(SUBJECT, pso);
                ci = pull.GetConsumerInformation();
                Assert.Equal(STREAM, ci.Stream);
            });
        }
        public void TestDontAutoAckIfUserAcks()
        {
            string mockAckReply = "mock-ack-reply.";

            Context.RunInJsServer(c =>
            {
                CreateMemoryStream(c, STREAM, SUBJECT, mockAckReply + "*");

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                // publish some messages
                JsPublish(js, SUBJECT, 2);

                // 1. auto ack true
                CountdownEvent latch = new CountdownEvent(2);
                bool flag            = true;

                // create our message handler, does not ack
                void Handler(object sender, MsgHandlerEventArgs args)
                {
                    if (flag)
                    {
                        args.Message.Reply = mockAckReply + "user";
                        args.Message.Ack();
                        flag = false;
                    }
                    args.Message.Reply = mockAckReply + "system";
                    latch.Signal();
                }

                // subscribe using the handler, auto ack true
                js.PushSubscribeAsync(SUBJECT, Handler, true);

                // wait for messages to arrive using the countdown latch.
                latch.Wait();

                IJetStreamPushSyncSubscription ssub = js.PushSubscribeSync(mockAckReply + "*");
                Msg m = ssub.NextMessage(1000);
                Assert.Equal(mockAckReply + "user", m.Subject);
                m = ssub.NextMessage(1000);
                Assert.Equal(mockAckReply + "system", m.Subject);
            });
        }
Example #17
0
        public void TestPublishAsyncVarieties()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);
                IJetStream js = c.CreateJetStreamContext();

                IList <Task <PublishAck> > tasks = new List <Task <PublishAck> >();

                tasks.Add(js.PublishAsync(SUBJECT, DataBytes(1)));

                Msg msg = new Msg(SUBJECT, DataBytes(2));
                tasks.Add(js.PublishAsync(msg));

                PublishOptions po = PublishOptions.Builder().Build();
                tasks.Add(js.PublishAsync(SUBJECT, DataBytes(3), po));

                msg = new Msg(SUBJECT, DataBytes(4));
                tasks.Add(js.PublishAsync(msg, po));

                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT);
                IList <Msg> list = ReadMessagesAck(sub);
                AssertContainsMessagesExact(list, 4);

                IList <ulong> seqnos = new List <ulong> {
                    1, 2, 3, 4
                };
                foreach (var task in tasks)
                {
                    AssertContainsPublishAck(task.Result, seqnos);
                }

                AssertTaskException(js.PublishAsync(Subject(999), null));
                AssertTaskException(js.PublishAsync(new Msg(Subject(999))));

                PublishOptions pox = PublishOptions.Builder().WithExpectedLastMsgId(MessageId(999)).Build();
                AssertTaskException(js.PublishAsync(Subject(999), null, pox));
                AssertTaskException(js.PublishAsync(new Msg(Subject(999)), pox));
            });
        }
Example #18
0
        public void TestAckReplySyncCoverage()
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT);
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server

                JsPublish(js, SUBJECT, "COVERAGE", 1);

                Msg message = sub.NextMessage(1000);
                Assert.NotNull(message);
                message.Reply = "$JS.ACK.stream.LS0k4eeN.1.1.1.1627472530542070600.0";

                Assert.Throws <NATSNoRespondersException>(() => message.AckSync(1000));
            });
        }
Example #19
0
        public void TestMoreCreateSubscriptionErrors()
        {
            Context.RunInJsServer(c =>
            {
                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT));
                Assert.Contains(JsSubNoMatchingStreamForSubject.Id, e.Message);

                // create the stream.
                CreateDefaultTestStream(c);

                // general pull push validation
                ConsumerConfiguration ccPush             = ConsumerConfiguration.Builder().WithDurable("pulldur").WithDeliverGroup("cantHave").Build();
                PullSubscribeOptions pullCantHaveDlvrGrp = PullSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PullSubscribe(SUBJECT, pullCantHaveDlvrGrp));
                Assert.Contains(JsSubPullCantHaveDeliverGroup.Id, e.Message);

                ccPush = ConsumerConfiguration.Builder().WithDurable("pulldur").WithDeliverSubject("cantHave").Build();
                PullSubscribeOptions pullCantHaveDlvrSub = PullSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PullSubscribe(SUBJECT, pullCantHaveDlvrSub));
                Assert.Contains(JsSubPullCantHaveDeliverSubject.Id, e.Message);

                ccPush = ConsumerConfiguration.Builder().WithMaxPullWaiting(1).Build();
                PushSubscribeOptions pushSo = PushSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, pushSo));
                Assert.Contains(JsSubPushCantHaveMaxPullWaiting.Id, e.Message);

                ccPush = ConsumerConfiguration.Builder().WithMaxPullWaiting(-1).Build();
                pushSo = PushSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                js.PushSubscribeSync(SUBJECT, pushSo);

                ccPush = ConsumerConfiguration.Builder().WithMaxBatch(1).Build();
                pushSo = PushSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                e      = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, pushSo));

                ccPush = ConsumerConfiguration.Builder().WithMaxBatch(-1).Build();
                pushSo = PushSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                js.PushSubscribeSync(SUBJECT, pushSo);
                Assert.Contains(JsSubPushCantHaveMaxBatch.Id, e.Message);

                ccPush = ConsumerConfiguration.Builder().WithMaxBytes(1).Build();
                pushSo = PushSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                e      = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, pushSo));

                ccPush = ConsumerConfiguration.Builder().WithMaxBytes(-1).Build();
                pushSo = PushSubscribeOptions.Builder().WithConfiguration(ccPush).Build();
                js.PushSubscribeSync(SUBJECT, pushSo);
                Assert.Contains(JsSubPushCantHaveMaxBytes.Id, e.Message);

                // create some consumers
                PushSubscribeOptions psoDurNoQ = PushSubscribeOptions.Builder().WithDurable("durNoQ").Build();
                js.PushSubscribeSync(SUBJECT, psoDurNoQ);

                PushSubscribeOptions psoDurYesQ = PushSubscribeOptions.Builder().WithDurable("durYesQ").Build();
                js.PushSubscribeSync(SUBJECT, "yesQ", psoDurYesQ);

                // already bound
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, psoDurNoQ));
                Assert.Contains(JsSubConsumerAlreadyBound.Id, e.Message);

                // queue match
                PushSubscribeOptions qmatch = PushSubscribeOptions.Builder()
                                              .WithDurable("qmatchdur").WithDeliverGroup("qmatchq").Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, "qnotmatch", qmatch));
                Assert.Contains(JsSubQueueDeliverGroupMismatch.Id, e.Message);

                // queue vs config
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, "notConfigured", psoDurNoQ));
                Assert.Contains(JsSubExistingConsumerNotQueue.Id, e.Message);

                PushSubscribeOptions psoNoVsYes = PushSubscribeOptions.Builder().WithDurable("durYesQ").Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, psoNoVsYes));
                Assert.Contains(JsSubExistingConsumerIsQueue.Id, e.Message);

                PushSubscribeOptions psoYesVsNo = PushSubscribeOptions.Builder().WithDurable("durYesQ").Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, "qnotmatch", psoYesVsNo));
                Assert.Contains(JsSubExistingQueueDoesNotMatchRequestedQueue.Id, e.Message);

                // flow control heartbeat push / pull
                ConsumerConfiguration ccFc = ConsumerConfiguration.Builder().WithDurable("ccFcDur").WithFlowControl(1000).Build();
                ConsumerConfiguration ccHb = ConsumerConfiguration.Builder().WithDurable("ccHbDur").WithIdleHeartbeat(1000).Build();

                PullSubscribeOptions psoPullCcFc = PullSubscribeOptions.Builder().WithConfiguration(ccFc).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PullSubscribe(SUBJECT, psoPullCcFc));
                Assert.Contains(JsSubFcHbNotValidPull.Id, e.Message);

                PullSubscribeOptions psoPullCcHb = PullSubscribeOptions.Builder().WithConfiguration(ccHb).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PullSubscribe(SUBJECT, psoPullCcHb));
                Assert.Contains(JsSubFcHbNotValidPull.Id, e.Message);

                PushSubscribeOptions psoPushCcFc = PushSubscribeOptions.Builder().WithConfiguration(ccFc).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, "cantHaveQ", psoPushCcFc));
                Assert.Contains(JsSubFcHbHbNotValidQueue.Id, e.Message);

                PushSubscribeOptions psoPushCcHb = PushSubscribeOptions.Builder().WithConfiguration(ccHb).Build();
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, "cantHaveQ", psoPushCcHb));
                Assert.Contains(JsSubFcHbHbNotValidQueue.Id, e.Message);
            });
        }
Example #20
0
 private void ChangeOkPush(IJetStream js, ConsumerConfiguration.ConsumerConfigurationBuilder builder)
 {
     js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.Builder().WithConfiguration(builder.Build()).Build()).Unsubscribe();
 }
Example #21
0
        public void TestConsumerIsNotModified()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);
                IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                // test with config in issue 105
                ConsumerConfiguration cc = ConsumerConfiguration.Builder()
                                           .WithDescription("desc")
                                           .WithAckPolicy(AckPolicy.Explicit)
                                           .WithDeliverPolicy(DeliverPolicy.All)
                                           .WithDeliverSubject(Deliver(1))
                                           .WithDeliverGroup(Queue(1))
                                           .WithDurable(Durable(1))
                                           .WithMaxAckPending(65000)
                                           .WithMaxDeliver(5)
                                           .WithReplayPolicy(ReplayPolicy.Instant)
                                           .Build();
                jsm.AddOrUpdateConsumer(STREAM, cc);

                IJetStream js = c.CreateJetStreamContext();

                PushSubscribeOptions pushOpts = PushSubscribeOptions.BindTo(STREAM, Durable(1));
                js.PushSubscribeSync(SUBJECT, Queue(1), pushOpts); // should not throw an error

                // testing numerics
                cc = ConsumerConfiguration.Builder()
                     .WithDeliverPolicy(DeliverPolicy.ByStartSequence)
                     .WithDeliverSubject(Deliver(21))
                     .WithDurable(Durable(21))
                     .WithStartSequence(42)
                     .WithMaxDeliver(43)
                     .WithRateLimitBps(44)
                     .WithMaxAckPending(45)
                     .Build();
                jsm.AddOrUpdateConsumer(STREAM, cc);

                pushOpts = PushSubscribeOptions.BindTo(STREAM, Durable(21));
                js.PushSubscribeSync(SUBJECT, pushOpts); // should not throw an error

                cc = ConsumerConfiguration.Builder()
                     .WithDurable(Durable(22))
                     .WithMaxPullWaiting(46)
                     .Build();
                jsm.AddOrUpdateConsumer(STREAM, cc);

                PullSubscribeOptions pullOpts = PullSubscribeOptions.BindTo(STREAM, Durable(22));
                js.PullSubscribe(SUBJECT, pullOpts); // should not throw an error

                // testing DateTime
                cc = ConsumerConfiguration.Builder()
                     .WithDeliverPolicy(DeliverPolicy.ByStartTime)
                     .WithDeliverSubject(Deliver(3))
                     .WithDurable(Durable(3))
                     .WithStartTime(DateTime.Now.AddHours(1))
                     .Build();
                jsm.AddOrUpdateConsumer(STREAM, cc);

                pushOpts = PushSubscribeOptions.BindTo(STREAM, Durable(3));
                js.PushSubscribeSync(SUBJECT, pushOpts); // should not throw an error

                // testing boolean and duration
                cc = ConsumerConfiguration.Builder()
                     .WithDeliverSubject(Deliver(4))
                     .WithDurable(Durable(4))
                     .WithFlowControl(1000)
                     .WithHeadersOnly(true)
                     .WithAckWait(2000)
                     .Build();
                jsm.AddOrUpdateConsumer(STREAM, cc);

                pushOpts = PushSubscribeOptions.BindTo(STREAM, Durable(4));
                js.PushSubscribeSync(SUBJECT, pushOpts); // should not throw an error

                // testing enums
                cc = ConsumerConfiguration.Builder()
                     .WithDeliverSubject(Deliver(5))
                     .WithDurable(Durable(5))
                     .WithDeliverPolicy(DeliverPolicy.Last)
                     .WithAckPolicy(AckPolicy.None)
                     .WithReplayPolicy(ReplayPolicy.Original)
                     .Build();
                jsm.AddOrUpdateConsumer(STREAM, cc);

                pushOpts = PushSubscribeOptions.BindTo(STREAM, Durable(5));
                js.PushSubscribeSync(SUBJECT, pushOpts); // should not throw an error
            });
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("NATS JetStream Push Subscribe Bind Durable", args, Usage)
                                    .DefaultStream("fs-stream")
                                    .DefaultSubject("fs-subject")
                                    .Build();

            string subjectWild = helper.Subject + ".*";
            string subjectA    = helper.Subject + ".A";
            string subjectB    = helper.Subject + ".B";

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // Create a JetStreamManagement context.
                    IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                    // Use the utility to create a stream stored in memory.
                    JsUtils.CreateStreamExitWhenExists(jsm, helper.Stream, subjectWild);

                    // Create our JetStream context to publish and receive JetStream messages.
                    IJetStream js = c.CreateJetStreamContext();

                    JsUtils.Publish(js, subjectA, 1);
                    JsUtils.Publish(js, subjectB, 1);
                    JsUtils.Publish(js, subjectA, 1);
                    JsUtils.Publish(js, subjectB, 1);

                    // 1. create a subscription that subscribes to the wildcard subject
                    ConsumerConfiguration cc = ConsumerConfiguration.Builder()
                                               .WithAckPolicy(AckPolicy.None) // don't want to worry about acking messages.
                                               .Build();

                    PushSubscribeOptions pso = PushSubscribeOptions.Builder()
                                               .WithConfiguration(cc)
                                               .Build();

                    IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(subjectWild, pso);
                    c.Flush(5000);

                    Msg m = sub.NextMessage(1000);
                    Console.WriteLine("\n1A1. Message should be from '" + subjectA + "', Sequence #1. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("1B2. Message should be from '" + subjectB + "', Sequence #2. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("1A3. Message should be from '" + subjectA + "', Sequence #3. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("1B4. Message should be from '" + subjectB + "', Sequence #4. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    // 2. create a subscription that subscribes only to the A subject
                    cc = ConsumerConfiguration.Builder()
                         .WithAckPolicy(AckPolicy.None)    // don't want to worry about acking messages.
                         .WithFilterSubject(subjectA)
                         .Build();

                    pso = PushSubscribeOptions.Builder()
                          .WithConfiguration(cc)
                          .Build();

                    sub = js.PushSubscribeSync(subjectWild, pso);
                    c.Flush(5000);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("\n2A1. Message should be from '" + subjectA + "', Sequence #1. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("2A3. Message should be from '" + subjectA + "', Sequence #3. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    try
                    {
                        sub.NextMessage(1000);
                        Console.WriteLine("2x. NOPE! Should not have gotten here");
                    }
                    catch (NATSTimeoutException) // timeout means there are no messages available
                    {
                        Console.WriteLine("2x. There was no message available.");
                    }

                    // 3. create a subscription that subscribes only to the A subject
                    cc = ConsumerConfiguration.Builder()
                         .WithAckPolicy(AckPolicy.None)    // don't want to worry about acking messages.
                         .WithFilterSubject(subjectB)
                         .Build();

                    pso = PushSubscribeOptions.Builder()
                          .WithConfiguration(cc)
                          .Build();

                    sub = js.PushSubscribeSync(subjectWild, pso);
                    c.Flush(5000);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("\n3A2. Message should be from '" + subjectB + "', Sequence #2. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    m = sub.NextMessage(1000);
                    Console.WriteLine("3A4. Message should be from '" + subjectB + "', Sequence #4. " +
                                      "It was: '" + m.Subject + "', Seq #" + m.MetaData.StreamSequence);

                    try
                    {
                        sub.NextMessage(1000);
                        Console.WriteLine("3x. NOPE! Should not have gotten here");
                    }
                    catch (NATSTimeoutException) // timeout means there are no messages available
                    {
                        Console.WriteLine("3x. There was no message available.");
                    }

                    Console.WriteLine();

                    // delete the stream since we are done with it.
                    jsm.DeleteStream(helper.Stream);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Example #23
0
        private static void SubPush(Context ctx, IConnection c, Stats stats, int id)
        {
            IJetStream js = c.CreateJetStreamContext(ctx.GetJetStreamOptions());
            IJetStreamPushSyncSubscription sub;

            if (ctx.Action.IsQueue)
            {
                // if we don't do this, multiple threads will try to make the same consumer because
                // when they start, the consumer does not exist. So force them do it one at a time.
                lock (QueueLock)
                {
                    sub = js.PushSubscribeSync(ctx.Subject, ctx.QueueName,
                                               ConsumerConfiguration.Builder()
                                               .WithAckPolicy(ctx.AckPolicy)
                                               .WithAckWait(Duration.OfSeconds(ctx.AckWaitSeconds))
                                               .WithDeliverGroup(ctx.QueueName)
                                               .BuildPushSubscribeOptions());
                }
            }
            else
            {
                sub = js.PushSubscribeSync(ctx.Subject,
                                           ConsumerConfiguration.Builder()
                                           .WithAckPolicy(ctx.AckPolicy)
                                           .WithAckWait(Duration.OfSeconds(ctx.AckWaitSeconds))
                                           .BuildPushSubscribeOptions());
            }

            int             rcvd         = 0;
            Msg             lastUnAcked  = null;
            int             unAckedCount = 0;
            int             unReported   = 0;
            string          label        = ctx.GetLabel(id);
            InterlockedLong counter      = ctx.GetSubscribeCounter(ctx.GetSubDurable(id));

            while (counter.Read() < ctx.MessageCount)
            {
                try
                {
                    stats.Start();
                    Msg  m        = sub.NextMessage(1000);
                    long hold     = stats.Elapsed();
                    long received = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                    stats.AcceptHold(hold);
                    stats.Count(m, received);
                    counter.Increment();
                    if ((lastUnAcked = AckMaybe(ctx, stats, m, ++unAckedCount)) == null)
                    {
                        unAckedCount = 0;
                    }
                    unReported = ReportMaybe(label, ctx, ++rcvd, ++unReported, "Messages Read");
                }
                catch (NATSTimeoutException)
                {
                    // normal timeout
                    long hold = stats.Elapsed();
                    AcceptHoldOnceStarted(label, stats, rcvd, hold);
                }
            }
            if (lastUnAcked != null)
            {
                _ack(stats, lastUnAcked);
            }
            Report(label, rcvd, "Finished Reading Messages");
        }
Example #24
0
        public void TestBindErrors()
        {
            Context.RunInJsServer(c =>
            {
                CreateDefaultTestStream(c);

                IJetStream js = c.CreateJetStreamContext();

                PushSubscribeOptions pushso    = PushSubscribeOptions.BindTo(STREAM, DURABLE);
                NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeSync(SUBJECT, pushso));
                Assert.Contains(JsSubConsumerNotFoundRequiredInBind.Id, e.Message);

                PullSubscribeOptions pullso = PullSubscribeOptions.BindTo(STREAM, DURABLE);
                e = Assert.Throws <NATSJetStreamClientException>(() => js.PullSubscribe(SUBJECT, pullso));
                Assert.Contains(JsSubConsumerNotFoundRequiredInBind.Id, e.Message);
            });
        }
Example #25
0
        public void TestFilterSubjectEphemeral()
        {
            Context.RunInJsServer(c =>
            {
                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                string subjectWild = SUBJECT + ".*";
                string subjectA    = SUBJECT + ".A";
                string subjectB    = SUBJECT + ".B";

                // create the stream.
                CreateMemoryStream(c, STREAM, subjectWild);

                JsPublish(js, subjectA, 1);
                JsPublish(js, subjectB, 1);
                JsPublish(js, subjectA, 1);
                JsPublish(js, subjectB, 1);

                // subscribe to the wildcard
                ConsumerConfiguration cc           = ConsumerConfiguration.Builder().WithAckPolicy(AckPolicy.None).Build();
                PushSubscribeOptions pso           = PushSubscribeOptions.Builder().WithConfiguration(cc).Build();
                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(subjectWild, pso);
                c.Flush(1000);

                Msg m = sub.NextMessage(1000);
                Assert.Equal(subjectA, m.Subject);
                Assert.Equal(1U, m.MetaData.StreamSequence);
                m = sub.NextMessage(1000);
                Assert.Equal(subjectB, m.Subject);
                Assert.Equal(2U, m.MetaData.StreamSequence);
                m = sub.NextMessage(1000);
                Assert.Equal(subjectA, m.Subject);
                Assert.Equal(3U, m.MetaData.StreamSequence);
                m = sub.NextMessage(1000);
                Assert.Equal(subjectB, m.Subject);
                Assert.Equal(4U, m.MetaData.StreamSequence);

                // subscribe to A
                cc  = ConsumerConfiguration.Builder().WithFilterSubject(subjectA).WithAckPolicy(AckPolicy.None).Build();
                pso = PushSubscribeOptions.Builder().WithConfiguration(cc).Build();
                sub = js.PushSubscribeSync(subjectWild, pso);
                c.Flush(1000);

                m = sub.NextMessage(1000);
                Assert.Equal(subjectA, m.Subject);
                Assert.Equal(1U, m.MetaData.StreamSequence);
                m = sub.NextMessage(1000);
                Assert.Equal(subjectA, m.Subject);
                Assert.Equal(3U, m.MetaData.StreamSequence);
                Assert.Throws <NATSTimeoutException>(() => sub.NextMessage(1000));

                // subscribe to B
                cc  = ConsumerConfiguration.Builder().WithFilterSubject(subjectB).WithAckPolicy(AckPolicy.None).Build();
                pso = PushSubscribeOptions.Builder().WithConfiguration(cc).Build();
                sub = js.PushSubscribeSync(subjectWild, pso);
                c.Flush(1000);

                m = sub.NextMessage(1000);
                Assert.Equal(subjectB, m.Subject);
                Assert.Equal(2U, m.MetaData.StreamSequence);
                m = sub.NextMessage(1000);
                Assert.Equal(subjectB, m.Subject);
                Assert.Equal(4U, m.MetaData.StreamSequence);
                Assert.Throws <NATSTimeoutException>(() => sub.NextMessage(1000));
            });
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("Push Subscribe Basic Sync", args, Usage)
                                    .DefaultStream("example-stream")
                                    .DefaultSubject("example-subject")
                                    .DefaultCount(0, true) // true indicated 0 means unlimited
                                                           // .DefaultDurable("push-sub-basic-sync-durable")
                                    .Build();

            int count = helper.Count < 1 ? int.MaxValue : helper.Count;

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // The stream (and data) must exist
                    JsUtils.ExitIfStreamNotExists(c, helper.Stream);

                    // Create our JetStream context.
                    IJetStream js = c.CreateJetStreamContext();

                    // Build our subscription options.
                    // * A push subscription means the server will "push" us messages.
                    // * Durable means the server will remember where we are if we use that name.
                    // * Durable can by null or empty, the builder treats them the same.
                    // * The stream name is not technically required. If it is not provided, the
                    //   code building the subscription will look it up by making a request to the server.
                    //   If you know the stream name, you might as well supply it and save a trip to the server.
                    PushSubscribeOptions so = PushSubscribeOptions.Builder()
                                              .WithStream(helper.Stream)
                                              .WithDurable(helper.Durable) // it's okay if this is null, the builder handles it
                                              .Build();

                    // Subscribe synchronously, then just wait for messages.
                    IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(helper.Subject, so);
                    c.Flush(5000);

                    int red = 0;
                    while (count > 0)
                    {
                        try
                        {
                            Msg msg = sub.NextMessage(1000);
                            Console.WriteLine("\nMessage Received:");
                            if (msg.HasHeaders)
                            {
                                Console.WriteLine("  Headers:");
                                foreach (string key in msg.Header.Keys)
                                {
                                    foreach (string value in msg.Header.GetValues(key))
                                    {
                                        Console.WriteLine($"    {key}: {value}");
                                    }
                                }
                            }

                            Console.WriteLine("  Subject: {0}\n  Data: {1}\n", msg.Subject, Encoding.UTF8.GetString(msg.Data));
                            Console.WriteLine("  " + msg.MetaData);

                            // Because this is a synchronous subscriber, there's no auto-ack.
                            // The default Consumer Configuration AckPolicy is Explicit
                            // so we need to ack the message or it'll be redelivered.
                            msg.Ack();

                            ++red;
                            --count;
                        }
                        catch (NATSTimeoutException) // timeout means there are no messages available
                        {
                            count = 0;               // ran out of messages
                        }
                    }

                    Console.WriteLine("\n" + red + " message(s) were received.\n");

                    sub.Unsubscribe();
                    c.Flush(5000);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Example #27
0
        public void TestJetStreamSubscribe()
        {
            Context.RunInJsServer(c =>
            {
                IJetStream js            = c.CreateJetStreamContext();
                IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                CreateDefaultTestStream(jsm);
                JsPublish(js);

                // default ephemeral subscription.
                IJetStreamPushSyncSubscription s = js.PushSubscribeSync(SUBJECT);
                Msg m = s.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal(DATA, Encoding.UTF8.GetString(m.Data));
                IList <String> names = jsm.GetConsumerNames(STREAM);
                Assert.Equal(1, names.Count);

                // default subscribe options // ephemeral subscription.
                s = js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.Builder().Build());
                m = s.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal(DATA, Encoding.UTF8.GetString(m.Data));
                names = jsm.GetConsumerNames(STREAM);
                Assert.Equal(2, names.Count);

                // set the stream
                PushSubscribeOptions pso = PushSubscribeOptions.Builder()
                                           .WithStream(STREAM).WithDurable(DURABLE).Build();
                s = js.PushSubscribeSync(SUBJECT, pso);
                m = s.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal(DATA, Encoding.UTF8.GetString(m.Data));
                names = jsm.GetConsumerNames(STREAM);
                Assert.Equal(3, names.Count);

                // coverage
                js.PushSubscribeSync(SUBJECT);
                js.PushSubscribeSync(SUBJECT, (PushSubscribeOptions)null);
                js.PushSubscribeSync(SUBJECT, QUEUE, null);
                js.PushSubscribeAsync(SUBJECT, (o, a) => {}, false);
                js.PushSubscribeAsync(SUBJECT, (o, a) => {}, false, null);
                js.PushSubscribeAsync(SUBJECT, QUEUE, (o, a) => {}, false, null);

                // bind with w/o subject
                jsm.AddOrUpdateConsumer(STREAM,
                                        ConsumerConfiguration.Builder()
                                        .WithDurable(Durable(101))
                                        .WithDeliverSubject(Deliver(101))
                                        .Build());
                PushSubscribeOptions psoBind = PushSubscribeOptions.BindTo(STREAM, Durable(101));
                js.PushSubscribeSync(null, psoBind).Unsubscribe();
                js.PushSubscribeSync("", psoBind).Unsubscribe();
                js.PushSubscribeAsync(null, (o, a) => { }, false, psoBind).Unsubscribe();
                js.PushSubscribeAsync("", (o, a) => { }, false, psoBind);

                jsm.AddOrUpdateConsumer(STREAM,
                                        ConsumerConfiguration.Builder()
                                        .WithDurable(Durable(102))
                                        .WithDeliverSubject(Deliver(102))
                                        .WithDeliverGroup(Queue(102))
                                        .Build());
                psoBind = PushSubscribeOptions.BindTo(STREAM, Durable(102));
                js.PushSubscribeSync(null, Queue(102), psoBind).Unsubscribe();
                js.PushSubscribeSync("", Queue(102), psoBind).Unsubscribe();
                js.PushSubscribeAsync(null, Queue(102), (o, a) => { }, false, psoBind).Unsubscribe();
                js.PushSubscribeAsync("", Queue(102), (o, a) => { }, false, psoBind);
            });
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("NATS JetStream Push Subscribe Queue Durable", args, Usage)
                                    .DefaultStream("qdur-stream")
                                    .DefaultSubject("qdur-subject")
                                    .DefaultQueue("qdur-queue")
                                    .DefaultDurable("qdur-durable")
                                    .DefaultDeliverSubject("qdur-deliver")
                                    .DefaultCount(100)
                                    .DefaultSubsCount(5)
                                    .Build();

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // Create a JetStreamManagement context.
                    IJetStreamManagement jsm = c.CreateJetStreamManagementContext();

                    // Use the utility to create a stream stored in memory.
                    JsUtils.CreateStreamExitWhenExists(jsm, helper.Stream, helper.Subject);

                    IJetStream js = c.CreateJetStreamContext();

                    Console.WriteLine();

                    // create the consumer ahead of time
                    ConsumerConfiguration cc = ConsumerConfiguration.Builder()
                                               .WithDurable(helper.Durable)
                                               .WithDeliverSubject(helper.DeliverSubject)
                                               .WithDeliverGroup(helper.Queue)
                                               .Build();
                    jsm.AddOrUpdateConsumer(helper.Stream, cc);

                    // we will just bind to that consumer
                    PushSubscribeOptions pso = PushSubscribeOptions.BindTo(helper.Stream, helper.Durable);

                    InterlockedLong           allReceived = new InterlockedLong();
                    IList <JsQueueSubscriber> subscribers = new List <JsQueueSubscriber>();
                    IList <Thread>            subThreads  = new List <Thread>();
                    for (int id = 1; id <= helper.SubsCount; id++)
                    {
                        // setup the subscription
                        IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(helper.Subject, helper.Queue, pso);

                        // create and track the runnable
                        JsQueueSubscriber qs = new JsQueueSubscriber(id, 100, js, sub, allReceived);
                        subscribers.Add(qs);

                        // create, track and start the thread
                        Thread t = new Thread(qs.Run);
                        subThreads.Add(t);
                        t.Start();
                    }
                    c.Flush(500); // flush outgoing communication with/to the server

                    // create and start the publishing
                    Thread pubThread = new Thread(() =>
                    {
                        for (int x = 1; x <= helper.Count; x++)
                        {
                            js.Publish(helper.Subject, Encoding.ASCII.GetBytes("Data # " + x));
                        }
                    });
                    pubThread.Start();

                    // wait for all threads to finish
                    pubThread.Join(10000);
                    foreach (Thread t in subThreads)
                    {
                        t.Join(10000);
                    }

                    foreach (JsQueueSubscriber qs in subscribers)
                    {
                        qs.Report();
                    }

                    Console.WriteLine();

                    // delete the stream since we are done with it.
                    jsm.DeleteStream(helper.Stream);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Example #29
0
        public void TestAcks()
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

                // Create our JetStream context.
                IJetStream js = c.CreateJetStreamContext();

                ConsumerConfiguration cc = ConsumerConfiguration.Builder().WithAckWait(1500).Build();

                // Build our subscription options.
                PushSubscribeOptions options = PushSubscribeOptions.Builder()
                                               .WithConfiguration(cc)
                                               .Build();

                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT, options);
                c.Flush(DefaultTimeout); // flush outgoing communication with/to the server

                // TERM
                JsPublish(js, SUBJECT, "TERM", 1);

                Msg m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("TERM1", Encoding.ASCII.GetString(m.Data));
                m.Term();

                AssertNoMoreMessages(sub);

                // Ack Wait timeout
                JsPublish(js, SUBJECT, "WAIT", 1);

                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("WAIT1", Encoding.ASCII.GetString(m.Data));
                Thread.Sleep(2000);
                m.Ack();

                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("WAIT1", Encoding.ASCII.GetString(m.Data));

                // In Progress
                JsPublish(js, SUBJECT, "PRO", 1);

                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("PRO1", Encoding.ASCII.GetString(m.Data));
                m.InProgress();
                Thread.Sleep(750);
                m.InProgress();
                Thread.Sleep(750);
                m.InProgress();
                Thread.Sleep(750);
                m.InProgress();
                Thread.Sleep(750);
                m.Ack();

                AssertNoMoreMessages(sub);

                // ACK Sync
                JsPublish(js, SUBJECT, "ACKSYNC", 1);
                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("ACKSYNC1", Encoding.ASCII.GetString(m.Data));
                m.AckSync(DefaultTimeout);

                AssertNoMoreMessages(sub);

                // NAK
                JsPublish(js, SUBJECT, "NAK", 1);

                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("NAK1", Encoding.ASCII.GetString(m.Data));
                m.Nak();

                m = sub.NextMessage(DefaultTimeout);
                Assert.NotNull(m);
                Assert.Equal("NAK1", Encoding.ASCII.GetString(m.Data));
                m.Ack();

                AssertNoMoreMessages(sub);

                JsPublish(js, SUBJECT, "NAK", 2, 1);

                m = sub.NextMessage(1000);
                Assert.NotNull(m);
                Assert.Equal("NAK2", Encoding.ASCII.GetString(m.Data));
                m.NakWithDelay(3000);

                Assert.Throws <NATSTimeoutException>(() => sub.NextMessage(500));

                m = sub.NextMessage(3000);
                Assert.NotNull(m);
                Assert.Equal("NAK2", Encoding.ASCII.GetString(m.Data));
                m.Ack();

                Assert.Throws <NATSTimeoutException>(() => sub.NextMessage(500));

                JsPublish(js, SUBJECT, "NAK", 3, 1);

                m = sub.NextMessage(1000);
                Assert.NotNull(m);
                Assert.Equal("NAK3", Encoding.ASCII.GetString(m.Data));
                m.NakWithDelay(Duration.OfSeconds(3)); // coverage to use both nakWithDelay

                Assert.Throws <NATSTimeoutException>(() => sub.NextMessage(500));

                m = sub.NextMessage(3000);
                Assert.NotNull(m);
                Assert.Equal("NAK3", Encoding.ASCII.GetString(m.Data));
                m.Ack();

                Assert.Throws <NATSTimeoutException>(() => sub.NextMessage(500));
            });
        }
Example #30
0
        public void TestDeliveryPolicy()
        {
            Context.RunInJsServer(c =>
            {
                IJetStreamManagement jsm = c.CreateJetStreamManagementContext();
                IJetStream js            = c.CreateJetStreamContext();

                CreateMemoryStream(jsm, STREAM, SUBJECT_STAR);

                string subjectA = SubjectDot("A");
                string subjectB = SubjectDot("B");

                js.Publish(subjectA, DataBytes(1));
                js.Publish(subjectA, DataBytes(2));
                Thread.Sleep(1500);
                js.Publish(subjectA, DataBytes(3));
                js.Publish(subjectB, DataBytes(91));
                js.Publish(subjectB, DataBytes(92));

                // DeliverPolicy.All
                PushSubscribeOptions pso = PushSubscribeOptions.Builder()
                                           .WithConfiguration(ConsumerConfiguration.Builder().WithDeliverPolicy(DeliverPolicy.All).Build())
                                           .Build();
                IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(subjectA, pso);
                Msg m1 = sub.NextMessage(1000);
                AssertMessage(m1, 1);
                Msg m2 = sub.NextMessage(1000);
                AssertMessage(m2, 2);
                Msg m3 = sub.NextMessage(1000);
                AssertMessage(m3, 3);

                // DeliverPolicy.Last
                pso = PushSubscribeOptions.Builder()
                      .WithConfiguration(ConsumerConfiguration.Builder().WithDeliverPolicy(DeliverPolicy.Last).Build())
                      .Build();
                sub   = js.PushSubscribeSync(subjectA, pso);
                Msg m = sub.NextMessage(1000);
                AssertMessage(m, 3);
                AssertNoMoreMessages(sub);

                // DeliverPolicy.New - No new messages between subscribe and next message
                pso = PushSubscribeOptions.Builder()
                      .WithConfiguration(ConsumerConfiguration.Builder().WithDeliverPolicy(DeliverPolicy.New).Build())
                      .Build();
                sub = js.PushSubscribeSync(subjectA, pso);
                AssertNoMoreMessages(sub);

                // DeliverPolicy.New - New message between subscribe and next message
                sub = js.PushSubscribeSync(subjectA, pso);
                js.Publish(subjectA, DataBytes(4));
                m = sub.NextMessage(1000);
                AssertMessage(m, 4);

                // DeliverPolicy.ByStartSequence
                pso = PushSubscribeOptions.Builder()
                      .WithConfiguration(ConsumerConfiguration.Builder()
                                         .WithDeliverPolicy(DeliverPolicy.ByStartSequence)
                                         .WithStartSequence(3)
                                         .Build())
                      .Build();
                sub = js.PushSubscribeSync(subjectA, pso);
                m   = sub.NextMessage(1000);
                AssertMessage(m, 3);
                m = sub.NextMessage(1000);
                AssertMessage(m, 4);

                // DeliverPolicy.ByStartTime
                pso = PushSubscribeOptions.Builder()
                      .WithConfiguration(ConsumerConfiguration.Builder()
                                         .WithDeliverPolicy(DeliverPolicy.ByStartTime)
                                         .WithStartTime(m3.MetaData.Timestamp.AddSeconds(-1))
                                         .Build())
                      .Build();
                sub = js.PushSubscribeSync(subjectA, pso);
                m   = sub.NextMessage(1000);
                AssertMessage(m, 3);
                m = sub.NextMessage(1000);
                AssertMessage(m, 4);

                // DeliverPolicy.LastPerSubject
                pso = PushSubscribeOptions.Builder()
                      .WithConfiguration(ConsumerConfiguration.Builder()
                                         .WithDeliverPolicy(DeliverPolicy.LastPerSubject)
                                         .WithFilterSubject(subjectA)
                                         .Build())
                      .Build();
                sub = js.PushSubscribeSync(subjectA, pso);
                m   = sub.NextMessage(1000);
                AssertMessage(m, 4);

                // DeliverPolicy.ByStartSequence with a deleted record
                PublishAck pa4 = js.Publish(subjectA, DataBytes(4));
                PublishAck pa5 = js.Publish(subjectA, DataBytes(5));
                js.Publish(subjectA, DataBytes(6));
                jsm.DeleteMessage(STREAM, pa4.Seq);
                jsm.DeleteMessage(STREAM, pa5.Seq);

                pso = ConsumerConfiguration.Builder()
                      .WithDeliverPolicy(DeliverPolicy.ByStartSequence)
                      .WithStartSequence(pa4.Seq)
                      .BuildPushSubscribeOptions();

                sub = js.PushSubscribeSync(subjectA, pso);
                m   = sub.NextMessage(1000);
                AssertMessage(m, 6);
            });
        }