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); } }