public void TestAckTerm() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // Build our subscription options. Durable is REQUIRED for pull based subscriptions PullSubscribeOptions options = PullSubscribeOptions.Builder().WithDurable(DURABLE).Build(); IJetStreamPullSubscription sub = js.PullSubscribe(SUBJECT, options); c.Flush(DefaultTimeout); // flush outgoing communication with/to the server // TERM JsPublish(js, SUBJECT, "TERM", 1); sub.Pull(1); Msg message = sub.NextMessage(1000); Assert.NotNull(message); Assert.Equal("TERM1", Encoding.ASCII.GetString(message.Data)); message.Term(); sub.Pull(1); AssertNoMoreMessages(sub); }); }
public void TestBindPull() { Context.RunInJsServer(c => { CreateDefaultTestStream(c); IJetStream js = c.CreateJetStreamContext(); JsPublish(js, SUBJECT, 1, 1); PullSubscribeOptions pso = PullSubscribeOptions.Builder() .WithDurable(DURABLE) .Build(); IJetStreamPullSubscription s = js.PullSubscribe(SUBJECT, pso); s.Pull(1); Msg m = s.NextMessage(1000); Assert.NotNull(m); Assert.Equal(Data(1), Encoding.ASCII.GetString(m.Data)); m.Ack(); s.Unsubscribe(); JsPublish(js, SUBJECT, 2, 1); pso = PullSubscribeOptions.Builder() .WithStream(STREAM) .WithDurable(DURABLE) .WithBind(true) .Build(); s = js.PullSubscribe(SUBJECT, pso); s.Pull(1); m = s.NextMessage(1000); Assert.NotNull(m); Assert.Equal(Data(2), Encoding.ASCII.GetString(m.Data)); m.Ack(); s.Unsubscribe(); JsPublish(js, SUBJECT, 3, 1); pso = PullSubscribeOptions.BindTo(STREAM, DURABLE); s = js.PullSubscribe(SUBJECT, pso); s.Pull(1); m = s.NextMessage(1000); Assert.NotNull(m); Assert.Equal(Data(3), Encoding.ASCII.GetString(m.Data)); }); }
public void TestAckWaitTimeout() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); ConsumerConfiguration cc = ConsumerConfiguration.Builder() .WithAckWait(1500) .Build(); PullSubscribeOptions pso = PullSubscribeOptions.Builder() .WithDurable(DURABLE) .WithConfiguration(cc) .Build(); IJetStreamPullSubscription sub = js.PullSubscribe(SUBJECT, pso); c.Flush(DefaultTimeout); // flush outgoing communication with/to the server // Ack Wait timeout JsPublish(js, SUBJECT, "WAIT", 1); sub.Pull(1); Msg message = sub.NextMessage(1000); Assert.NotNull(message); Assert.Equal("WAIT1", Encoding.ASCII.GetString(message.Data)); Thread.Sleep(2000); sub.Pull(1); message = sub.NextMessage(1000); Assert.NotNull(message); Assert.Equal("WAIT1", Encoding.ASCII.GetString(message.Data)); sub.Pull(1); AssertNoMoreMessages(sub); }); }
public void TestPullExpires() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // Build our subscription options. Durable is REQUIRED for pull based subscriptions PullSubscribeOptions options = PullSubscribeOptions.Builder().WithDurable(DURABLE).Build(); // Subscribe synchronously. IJetStreamPullSubscription sub = js.PullSubscribe(SUBJECT, options); AssertSubscription(sub, STREAM, DURABLE, null, true); c.Flush(DefaultTimeout); // flush outgoing communication with/to the server int expires = 250; // millis // publish 10 messages JsPublish(js, SUBJECT, "A", 5); sub.PullExpiresIn(10, expires); IList <Msg> messages = ReadMessagesAck(sub); Assert.Equal(5, messages.Count); AssertAllJetStream(messages); Thread.Sleep(expires); // make sure the pull actually expires JsPublish(js, SUBJECT, "B", 10); sub.PullExpiresIn(10, expires); messages = ReadMessagesAck(sub); Assert.Equal(10, messages.Count); Thread.Sleep(expires); // make sure the pull actually expires JsPublish(js, SUBJECT, "C", 5); sub.PullExpiresIn(10, expires); messages = ReadMessagesAck(sub); Assert.Equal(5, messages.Count); AssertAllJetStream(messages); Thread.Sleep(expires); // make sure the pull actually expires JsPublish(js, SUBJECT, "D", 10); sub.Pull(10); messages = ReadMessagesAck(sub); Assert.Equal(10, messages.Count); JsPublish(js, SUBJECT, "E", 5); sub.PullExpiresIn(10, expires); // using millis version here messages = ReadMessagesAck(sub); Assert.Equal(5, messages.Count); AssertAllJetStream(messages); Thread.Sleep(expires); // make sure the pull actually expires JsPublish(js, SUBJECT, "F", 10); sub.PullNoWait(10); messages = ReadMessagesAck(sub); Assert.Equal(10, messages.Count); JsPublish(js, SUBJECT, "G", 5); sub.PullExpiresIn(10, expires); // using millis version here messages = ReadMessagesAck(sub); Assert.Equal(5, messages.Count); AssertAllJetStream(messages); JsPublish(js, SUBJECT, "H", 10); messages = sub.Fetch(10, expires); Assert.Equal(10, messages.Count); AssertAllJetStream(messages); JsPublish(js, SUBJECT, "I", 5); sub.PullExpiresIn(10, expires); messages = ReadMessagesAck(sub); Assert.Equal(5, messages.Count); AssertAllJetStream(messages); Thread.Sleep(expires); // make sure the pull actually expires }); }
public void TestBasic() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // Build our subscription options. Durable is REQUIRED for pull based subscriptions PullSubscribeOptions options = PullSubscribeOptions.Builder().WithDurable(DURABLE).Build(); // Pull Subscribe. IJetStreamPullSubscription sub = js.PullSubscribe(SUBJECT, options); AssertSubscription(sub, STREAM, DURABLE, null, true); c.Flush(DefaultTimeout); // flush outgoing communication with/to the server // publish some amount of messages, but not entire pull size JsPublish(js, SUBJECT, "A", 4); // start the pull sub.Pull(10); // read what is available, expect 4 IList <Msg> messages = ReadMessagesAck(sub); int total = messages.Count; ValidateRedAndTotal(4, messages.Count, 4, total); // publish some more covering our initial pull and more JsPublish(js, SUBJECT, "B", 10); // read what is available, expect 6 more messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(6, messages.Count, 10, total); // read what is available, should be zero since we didn't re-pull messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(0, messages.Count, 10, total); // re-issue the pull sub.Pull(10); // read what is available, should be 4 left over messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(4, messages.Count, 14, total); // publish some more JsPublish(js, SUBJECT, "C", 10); // read what is available, should be 6 since we didn't finish the last batch messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(6, messages.Count, 20, total); // re-issue the pull, but a smaller amount sub.Pull(2); // read what is available, should be 5 since we changed the pull size messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(2, messages.Count, 22, total); // re-issue the pull, since we got the full batch size sub.Pull(2); // read what is available, should be zero since we didn't re-pull messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(2, messages.Count, 24, total); // re-issue the pull, any amount there are no messages sub.Pull(1); // read what is available, there are none messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(0, messages.Count, 24, total); }); }
public static void Main(string[] args) { ArgumentHelper helper = new ArgumentHelperBuilder("Pull Subscription using primitive Batch Size", args, Usage) .DefaultStream("pull-stream") .DefaultSubject("pull-subject") .DefaultDurable("pull-durable") .DefaultCount(15) .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 our JetStream context. IJetStream js = c.CreateJetStreamContext(); // Start publishing the messages, don't wait for them to finish, simulating an outside producer. JsUtils.PublishInBackground(js, helper.Subject, "pull-message", helper.Count); // Build our subscription options. Durable is REQUIRED for pull based subscriptions PullSubscribeOptions pullOptions = PullSubscribeOptions.Builder() .WithDurable(helper.Durable) // required .Build(); // subscribe IJetStreamPullSubscription sub = js.PullSubscribe(helper.Subject, pullOptions); c.Flush(1000); bool keepGoing = true; int red = 0; while (keepGoing && red < helper.Count) { sub.Pull(10); int round = 0; while (keepGoing && round < 10) { try { Msg m = sub.NextMessage(1000); // first message Console.WriteLine($"{++red}. Message: {m}"); m.Ack(); round++; } catch (NATSTimeoutException) // timeout means there are no messages available { keepGoing = false; } } } // delete the stream since we are done with it. jsm.DeleteStream(helper.Stream); } } catch (Exception ex) { helper.ReportException(ex); } }
public static void Main(string[] args) { ArgumentHelper helper = new ArgumentHelperBuilder("Pull Subscription using primitive Batch Size, Use Cases", args, Usage) .DefaultStream("pull-stream") .DefaultSubject("pull-subject") .DefaultDurable("pull-durable") .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 our JetStream context. IJetStream js = c.CreateJetStreamContext(); // Build our subscription options. Durable is REQUIRED for pull based subscriptions PullSubscribeOptions pullOptions = PullSubscribeOptions.Builder() .WithDurable(helper.Durable) // required .Build(); // 0.1 Initialize. subscription // 0.2 Flush outgoing communication with/to the server, useful when app is both JsUtils.Publishing and subscribing. // 0.3 Start the pull, you don't have to call this again because AckMode.NEXT // - When we ack a batch message the server starts preparing or adding to the next batch. Console.WriteLine("\n----------\n0. Initialize the subscription and pull."); IJetStreamPullSubscription sub = js.PullSubscribe(helper.Subject, pullOptions); c.Flush(1000); sub.Pull(10); // 1. JsUtils.Publish some that is less than the batch size. // - Do this first as data will typically be published first. Console.WriteLine("----------\n1. JsUtils.Publish some amount of messages, but not entire batch size."); JsUtils.Publish(js, helper.Subject, "A", 4); IList <Msg> messages = JsUtils.ReadMessagesAck(sub); Console.WriteLine("We should have received 4 total messages, we received: " + messages.Count); // 2. JsUtils.Publish some more covering our pull size... // - Read what is available, expect only 6 b/c 4 + 6 = 10 Console.WriteLine("----------\n2. JsUtils.Publish more than the remaining batch size."); JsUtils.Publish(js, helper.Subject, "B", 10); messages = JsUtils.ReadMessagesAck(sub); Console.WriteLine("We should have received 6 total messages, we received: " + messages.Count); // 3. There are still 4 messages from B, but the batch was finished // - won't get any messages until a pull is issued. Console.WriteLine("----------\n3. Read without re-issue."); messages = JsUtils.ReadMessagesAck(sub); Console.WriteLine("We should have received 0 total messages, we received: " + messages.Count); // 4. re-issue the pull to get the last 4 Console.WriteLine("----------\n4. Re-issue to get the last 4."); sub.Pull(10); messages = JsUtils.ReadMessagesAck(sub); Console.WriteLine("We should have received 4 total messages, we received: " + messages.Count); Console.WriteLine("----------\n"); // delete the stream since we are done with it. jsm.DeleteStream(helper.Stream); } } catch (Exception ex) { helper.ReportException(ex); } }