public static void Main(string[] args) { ArgumentHelper helper = new ArgumentHelperBuilder("Pull Subscription using primitive Expires In", args, Usage) .DefaultStream("fetch-stream") .DefaultSubject("fetch-subject") .DefaultDurable("fetch-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, "fetch-message", helper.Count); // Build our consumer configuration and subscription options. // make sure the ack wait is sufficient to handle the reading and processing of the batch. // Durable is REQUIRED for pull based subscriptions ConsumerConfiguration cc = ConsumerConfiguration.Builder() .WithAckWait(2500) .Build(); PullSubscribeOptions pullOptions = PullSubscribeOptions.Builder() .WithDurable(helper.Durable) // required .WithConfiguration(cc) .Build(); // subscribe IJetStreamPullSubscription sub = js.PullSubscribe(helper.Subject, pullOptions); c.Flush(1000); int red = 0; while (red < helper.Count) { IList <Msg> list = sub.Fetch(10, 1000); foreach (Msg m in list) { Console.WriteLine($"{++red}. Message: {m}"); m.Ack(); } } // delete the stream since we are done with it. jsm.DeleteStream(helper.Stream); } } catch (Exception ex) { helper.ReportException(ex); } }
private static void _subPullFetch(Context ctx, Stats stats, IJetStreamPullSubscription sub, int id, string counterKey) { int rcvd = 0; Msg lastUnAcked = null; int unAckedCount = 0; int unReported = 0; string label = ctx.GetLabel(id); InterlockedLong counter = ctx.GetSubscribeCounter(counterKey); while (counter.Read() < ctx.MessageCount) { stats.Start(); IList <Msg> list = sub.Fetch(ctx.BatchSize, 500); long hold = stats.Elapsed(); long received = DateTimeOffset.Now.ToUnixTimeMilliseconds(); int lc = list.Count; if (lc > 0) { foreach (Msg m in list) { stats.Count(m, received); counter.Increment(); if ((lastUnAcked = AckMaybe(ctx, stats, m, ++unAckedCount)) == null) { unAckedCount = 0; } } rcvd += lc; unReported = ReportMaybe(label, ctx, rcvd, unReported + lc, "Messages Read"); } AcceptHoldOnceStarted(label, stats, rcvd, hold); } if (lastUnAcked != null) { _ack(stats, lastUnAcked); } Report(label, rcvd, "Finished Reading Messages"); }
public static void Main(string[] args) { ArgumentHelper helper = new ArgumentHelperBuilder("Pull Subscription using primitive Expires In", args, Usage) .DefaultStream("fetch-uc-stream") .DefaultSubject("fetch-uc-subject") .DefaultDurable("fetch-uc-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(); // Build our consumer configuration and subscription options. // make sure the ack wait is sufficient to handle the reading and processing of the batch. // Durable is REQUIRED for pull based subscriptions ConsumerConfiguration cc = ConsumerConfiguration.Builder() .WithAckWait(2500) .Build(); PullSubscribeOptions pullOptions = PullSubscribeOptions.Builder() .WithDurable(helper.Durable) // required .WithConfiguration(cc) .Build(); // 0.1 Initialize. subscription // 0.2 Flush outgoing communication with/to the server, useful when app is both JsUtils.Publishing and subscribing. Console.WriteLine("\n----------\n0. Initialize the subscription and pull."); IJetStreamPullSubscription sub = js.PullSubscribe(helper.Subject, pullOptions); c.Flush(1000); // 1. Fetch, but there are no messages yet. // - Read the messages, get them all (0) Console.WriteLine("----------\n1. There are no messages yet"); IList <Msg> messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 0 total messages, we received: " + messages.Count); // 2. Publish 10 messages // - Fetch messages, get 10 Console.WriteLine("----------\n2. Publish 10 which satisfies the batch"); JsUtils.Publish(js, helper.Subject, "A", 10); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count); // 3. Publish 20 messages // - Fetch messages, only get 10 Console.WriteLine("----------\n3. Publish 20 which is larger than the batch size."); JsUtils.Publish(js, helper.Subject, "B", 20); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count); // 4. There are still messages left from the last // - Fetch messages, get 10 Console.WriteLine("----------\n4. Get the rest of the JsUtils.Publish."); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count); // 5. Publish 5 messages // - Fetch messages, get 5 // - Since there are less than batch size we only get what the server has. Console.WriteLine("----------\n5. Publish 5 which is less than batch size."); JsUtils.Publish(js, helper.Subject, "C", 5); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 5 total messages, we received: " + messages.Count); // 6. Publish 15 messages // - Fetch messages, only get 10 Console.WriteLine("----------\n6. Publish 15 which is more than the batch size."); JsUtils.Publish(js, helper.Subject, "D", 15); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count); // 7. There are 5 messages left // - Fetch messages, only get 5 Console.WriteLine("----------\n7. There are 5 messages left."); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 5 messages, we received: " + messages.Count); // 8. Read but don't ack. // - Fetch messages, get 10, but either take too long to ack them or don't ack them Console.WriteLine("----------\n8. Fetch but don't ack."); JsUtils.Publish(js, helper.Subject, "E", 10); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); Console.WriteLine("We should have received 10 message, we received: " + messages.Count); Thread.Sleep(3000); // longer than the ackWait // 9. Fetch messages, // - get the 10 messages we didn't ack Console.WriteLine("----------\n9. Fetch, get the messages we did not ack."); messages = sub.Fetch(10, 3000); JsUtils.Report(messages); foreach (Msg m in messages) { m.Ack(); } Console.WriteLine("We should have received 10 message, 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); } }
public void TestFetch() { Console.SetOut(new ConsoleWriter(output)); Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); int fetchMs = 3000; int ackWaitMs = fetchMs * 2; ConsumerConfiguration cc = ConsumerConfiguration.Builder() .WithAckWait(ackWaitMs) .Build(); PullSubscribeOptions options = PullSubscribeOptions.Builder() .WithDurable(DURABLE) .WithConfiguration(cc) .Build(); IJetStreamPullSubscription sub = js.PullSubscribe(SUBJECT, options); AssertSubscription(sub, STREAM, DURABLE, null, true); c.Flush(DefaultTimeout); // flush outgoing communication with/to the server IList <Msg> messages = sub.Fetch(10, fetchMs); ValidateRead(0, messages.Count); AckAll(messages); Thread.Sleep(ackWaitMs); // let the pull expire JsPublish(js, SUBJECT, "A", 10); messages = sub.Fetch(10, fetchMs); ValidateRead(10, messages.Count); AckAll(messages); JsPublish(js, SUBJECT, "B", 20); messages = sub.Fetch(10, fetchMs); ValidateRead(10, messages.Count); AckAll(messages); messages = sub.Fetch(10, fetchMs); ValidateRead(10, messages.Count); AckAll(messages); JsPublish(js, SUBJECT, "C", 5); messages = sub.Fetch(10, fetchMs); ValidateRead(5, messages.Count); AckAll(messages); Thread.Sleep(fetchMs * 2); // let the pull expire JsPublish(js, SUBJECT, "D", 15); messages = sub.Fetch(10, fetchMs); ValidateRead(10, messages.Count); AckAll(messages); messages = sub.Fetch(10, fetchMs); ValidateRead(5, messages.Count); AckAll(messages); JsPublish(js, SUBJECT, "E", 10); messages = sub.Fetch(10, fetchMs); ValidateRead(10, messages.Count); Thread.Sleep(ackWaitMs); messages = sub.Fetch(10, fetchMs); ValidateRead(10, messages.Count); AckAll(messages); }); }
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 }); }