private void _testPushDurableSubSync(string durable, string deliverSubject, IConnection nc, PushSyncSubSupplier supplier) { IJetStreamPushSyncSubscription sub = supplier.Invoke(); AssertSubscription(sub, STREAM, durable, deliverSubject, false); // read what is available IList <Msg> messages = ReadMessagesAck(sub); int total = messages.Count; ValidateRedAndTotal(5, messages.Count, 5, total); // read again, nothing should be there messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(0, messages.Count, 5, total); sub.Unsubscribe(); nc.Flush(1000); // flush outgoing communication with/to the server // re-subscribe sub = supplier.Invoke(); nc.Flush(1000); // flush outgoing communication with/to the server // read again, nothing should be there messages = ReadMessagesAck(sub); total += messages.Count; ValidateRedAndTotal(0, messages.Count, 5, total); sub.Unsubscribe(); nc.Flush(1000); // flush outgoing communication with/to the server }
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); }); }
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); }); }
private void VisitSubject(string subject, DeliverPolicy deliverPolicy, bool headersOnly, bool ordered, Action <Msg> action) { PushSubscribeOptions pso = PushSubscribeOptions.Builder() .WithOrdered(ordered) .WithConfiguration( ConsumerConfiguration.Builder() .WithAckPolicy(AckPolicy.None) .WithDeliverPolicy(deliverPolicy) .WithHeadersOnly(headersOnly) .Build()) .Build(); IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(subject, pso); try { bool lastTimedOut = false; ulong pending = sub.GetConsumerInformation().CalculatedPending; while (pending > 0) // no need to loop if nothing pending { try { Msg m = sub.NextMessage(js.Timeout); action.Invoke(m); if (--pending == 0) { return; } lastTimedOut = false; } catch (NATSTimeoutException) { if (lastTimedOut) { return; // two timeouts in a row is enough } lastTimedOut = true; } } } finally { sub.Unsubscribe(); } }
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]); }); }
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); } }
public static void Main(string[] args) { ArgumentHelper helper = new ArgumentHelperBuilder("NATS JetStream Push Subscribe Bind Durable", args, Usage) .DefaultStream("example-stream") .DefaultSubject("example-subject") .DefaultDurable("bind-durable") .DefaultDeliverSubject("bind-deliver") .DefaultCount(0, true) // true indicated 0 means unlimited .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); // The durable consumer must already exist. Usually it would be made in configuration // or via the NATS CLI but we are making it here. // Important: The consumer must have a deliver subject when made this way or it will be // understood to be a pull consumer by the server. // NOTE: If you ran this example already, the consumer will have been created // This is not a problem if it is exactly the same. Most ConsumerConfiguration // properties are not modifiable once created. ConsumerConfiguration cc = ConsumerConfiguration.Builder() .WithDurable(helper.Durable) .WithDeliverSubject(helper.DeliverSubject) .Build(); c.CreateJetStreamManagementContext().AddOrUpdateConsumer(helper.Stream, cc); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // bind subscribe to the stream - either variety will work // V1. Version designed specifically for this purpose. PushSubscribeOptions so = PushSubscribeOptions.BindTo(helper.Stream, helper.Durable); // V2. optional long form // PushSubscribeOptions so = PushSubscribeOptions.Builder() // .WithBind(true) // .WithStream(helper.Stream) // .WithDurable(helper.Durable) // .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); } }