public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("Push Subscribe Basic Async", args, Usage)
                                    .DefaultStream("example-stream")
                                    .DefaultSubject("example-subject")
                                    .Build();

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    JsUtils.CreateStreamWhenDoesNotExist(c, helper.Stream, helper.Subject);

                    IJetStream js = c.CreateJetStreamContext();

                    new Thread(() =>
                    {
                        js.PushSubscribeAsync(helper.Subject, (sender, a) =>
                        {
                            a.Message.Ack();
                            Console.WriteLine(Encoding.UTF8.GetString(a.Message.Data));
                        }, false);
                    }).Start();

                    Thread.Sleep(3000);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Esempio n. 2
0
        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);
            }
        }
        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);
            }
        }
Esempio n. 4
0
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("JetStream Publish", args, Usage)
                                    .DefaultStream("example-stream")
                                    .DefaultSubject("example-subject")
                                    .DefaultPayload("Hello")
                                    .DefaultCount(10)
                                    .Build();

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // Use the utility to create a stream stored in memory.
                    JsUtils.CreateStreamOrUpdateSubjects(c, helper.Stream, helper.Subject);

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

                    int stop = helper.Count < 2 ? 2 : helper.Count + 1;
                    for (int x = 1; x < stop; x++)
                    {
                        // make unique message data if you want more than 1 message
                        byte[] data = helper.Count < 2
                            ? Encoding.UTF8.GetBytes(helper.Payload)
                            : Encoding.UTF8.GetBytes(helper.Payload + "-" + x);

                        // Publish a message and print the results of the publish acknowledgement.
                        Msg msg = new Msg(helper.Subject, null, helper.Header, data);

                        // We'll use the defaults for this simple example, but there are options
                        // to constrain publishing to certain streams, expect sequence numbers and
                        // more. See the JetStreamPublishWithOptionsUseCases example for details.
                        // An exception will be thrown if there is a failure.
                        PublishAck pa = js.Publish(msg);
                        Console.WriteLine("Published message '{0}' on subject '{1}', stream '{2}', seqno '{3}'.",
                                          Encoding.UTF8.GetString(data), helper.Subject, pa.Stream, pa.Seq);
                    }
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Esempio n. 5
0
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("KeyValueFull", args, Usage)
                                    .DefaultBucket("exampleBucket")
                                    .DefaultDescription("Example Description")
                                    .Build();

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // get the kv management context
                    IKeyValueManagement kvm = c.CreateKeyValueManagementContext();

                    // create the bucket
                    KeyValueConfiguration kvc = KeyValueConfiguration.Builder()
                                                .WithName(helper.Bucket)
                                                .WithDescription(helper.Description)
                                                .WithMaxHistoryPerKey(5)
                                                .WithStorageType(StorageType.Memory)
                                                .Build();

                    KeyValueStatus kvs = kvm.Create(kvc);
                    Console.WriteLine(kvs);

                    // get the kv context for the specific bucket
                    IKeyValue kv = c.CreateKeyValueContext(helper.Bucket);

                    // Put some keys. Each key is put in a subject in the bucket (stream)
                    // The put returns the revision number in the bucket (stream)
                    Console.WriteLine("\n1. Put");

                    ulong seq = kv.Put(ByteKey, Encoding.UTF8.GetBytes("Byte Value 1"));
                    Console.WriteLine("Revision number should be 1, got " + seq);

                    seq = kv.Put(StringKey, "String Value 1");
                    Console.WriteLine("Revision number should be 2, got " + seq);

                    seq = kv.Put(LongKey, 1);
                    Console.WriteLine("Revision number should be 3, got " + seq);

                    // retrieve the values. all types are stored as bytes
                    // so you can always get the bytes directly
                    Console.WriteLine("\n2. Get Value (Bytes)");

                    byte[] bvalue = kv.Get(ByteKey).Value;
                    Console.WriteLine(ByteKey + " from Value property: " + Encoding.UTF8.GetString(bvalue));

                    bvalue = kv.Get(StringKey).Value;
                    Console.WriteLine(StringKey + " from Value property: " + Encoding.UTF8.GetString(bvalue));

                    bvalue = kv.Get(LongKey).Value;
                    Console.WriteLine(LongKey + " from Value property: " + Encoding.UTF8.GetString(bvalue));

                    // if you know the value is not binary and can safely be read
                    // as a UTF-8 string, the ValueAsString function is ok to use
                    Console.WriteLine("\n3. Get String Value");

                    String svalue = kv.Get(ByteKey).ValueAsString();
                    Console.WriteLine(ByteKey + " from ValueAsString(): " + svalue);

                    svalue = kv.Get(StringKey).ValueAsString();
                    Console.WriteLine(StringKey + " from ValueAsString(): " + svalue);

                    svalue = kv.Get(LongKey).ValueAsString();
                    Console.WriteLine(LongKey + " from ValueAsString(): " + svalue);

                    // if you know the value is a long, you can use
                    // the getLongValue method
                    // if it's not a number a NumberFormatException is thrown
                    Console.WriteLine("\n4. Get Long Value");

                    long lvalue;
                    bool bLongGet = kv.Get(LongKey).TryGetLongValue(out lvalue);
                    Console.WriteLine(LongKey + " from getValueAsLong: " + lvalue);

                    bLongGet = kv.Get(StringKey).TryGetLongValue(out lvalue);
                    if (!bLongGet)
                    {
                        Console.WriteLine(StringKey + " value is not a long!");
                    }

                    // entry gives detail about latest record of the key
                    Console.WriteLine("\n5. Get Entry");

                    KeyValueEntry entry = kv.Get(ByteKey);
                    Console.WriteLine(ByteKey + " entry: " + entry);

                    entry = kv.Get(StringKey);
                    Console.WriteLine(StringKey + " entry: " + entry);

                    entry = kv.Get(LongKey);
                    Console.WriteLine(LongKey + " entry: " + entry);

                    // delete a key
                    Console.WriteLine("\n6. Delete a key");
                    kv.Delete(ByteKey);

                    // it's value is now null
                    // it's value is now null but there is a delete tombstone
                    KeyValueEntry kve = kv.Get(ByteKey);
                    Console.WriteLine("Delete tombstone entry: " + kve);
                    Console.WriteLine("Revision number should be 4, got " + kve.Revision);
                    Console.WriteLine("Deleted value should be null: " + (kve.Value == null));

                    // if the key does not exist there is no entry at all
                    Console.WriteLine("\n7.1 Keys does not exist");
                    kve = kv.Get(NotFound);
                    Console.WriteLine($"Entry for {NotFound} should be null: {kve == null}");

                    // if the key has been deleted there is an entry for it
                    // but the value will be null
                    Console.WriteLine("\n7.2 Keys not found");
                    bvalue = kv.Get(ByteKey).Value;
                    Console.WriteLine($"{ByteKey} byte value should be null: {bvalue == null}");

                    svalue = kv.Get(ByteKey).ValueAsString();
                    Console.WriteLine($"{ByteKey} string value should be null: " + (svalue == null));

                    bLongGet = kv.Get(ByteKey).TryGetLongValue(out lvalue);
                    if (!bLongGet)
                    {
                        Console.WriteLine(ByteKey + " value is not a long!");
                    }

                    // Update values. You can even update a deleted key
                    Console.WriteLine("\n8.1 Update values");
                    seq = kv.Put(ByteKey, Encoding.UTF8.GetBytes("Byte Value 2"));
                    Console.WriteLine("Revision number should be 5, got " + seq);

                    seq = kv.Put(StringKey, "String Value 2");
                    Console.WriteLine("Revision number should be 6, got " + seq);

                    seq = kv.Put(LongKey, 2);
                    Console.WriteLine("Revision number should be 7, got " + seq);

                    // values after updates
                    Console.WriteLine("\n8.2 Values after update");

                    svalue = kv.Get(ByteKey).ValueAsString();
                    Console.WriteLine(ByteKey + " from ValueAsString(): " + svalue);

                    svalue = kv.Get(StringKey).ValueAsString();
                    Console.WriteLine(StringKey + " from ValueAsString(): " + svalue);

                    bLongGet = kv.Get(LongKey).TryGetLongValue(out lvalue);
                    Console.WriteLine(LongKey + " from TryGetLongValue: " + lvalue);

                    // let's check the bucket info
                    Console.WriteLine("\n9.1 Bucket before update/delete");
                    kvs = kvm.GetBucketInfo(helper.Bucket);
                    Console.WriteLine(kvs);

                    kvc = KeyValueConfiguration.Builder(kvs.Config)
                          .WithDescription(helper.Description + "-changed")
                          .WithMaxHistoryPerKey(6)
                          .Build();
                    kvs = kvm.Update(kvc);
                    Console.WriteLine("\n9.2 Bucket after update");
                    Console.WriteLine(kvs);

                    // delete the bucket
                    Console.WriteLine("\n9.3 Delete");
                    kvm.Delete(helper.Bucket);

                    try {
                        kvm.GetBucketInfo(helper.Bucket);
                        Console.WriteLine("UH OH! Bucket should not have been found!");
                    }
                    catch (NATSJetStreamException) {
                        Console.WriteLine("Bucket was not found!");
                    }
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
        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 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);
            }
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("Pull Subscription using primitive Expires In, Use Cases", args, Usage)
                                    .DefaultStream("expires-in-uc-stream")
                                    .DefaultSubject("expires-in-uc-subject")
                                    .DefaultDurable("expires-in-uc-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);

                    // 1. Publish some that is less than the batch size.
                    Console.WriteLine("\n----------\n1. Publish some amount of messages, but not entire batch size.");
                    JsUtils.Publish(js, helper.Subject, "A", 6);
                    sub.PullExpiresIn(10, 1200);
                    IList <Msg> messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 6 total messages, we received: " + messages.Count);

                    // 2. Publish some more covering our pull size...
                    Console.WriteLine("----------\n2. Publish more than the batch size.");
                    sub.PullExpiresIn(10, 1200);
                    JsUtils.Publish(js, helper.Subject, "B", 14);
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 10 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 issuing a pull.");
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    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. Issue the pull to get the last 4.");
                    sub.PullExpiresIn(10, 1200);
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 4 total messages, we received: " + messages.Count);

                    // 5. publish a lot of messages
                    Console.WriteLine("----------\n5. Publish a lot of messages. The last pull was under the batch size.");
                    Console.WriteLine("   Issue another pull with batch size less than number of messages.");
                    JsUtils.Publish(js, helper.Subject, "C", 25);
                    sub.PullExpiresIn(10, 1200);
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count);

                    // 6. there are still more messages
                    Console.WriteLine("----------\n6. Still more messages. Issue another pull with batch size less than number of messages.");
                    sub.PullExpiresIn(10, 1200);
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count);

                    // 7. there are still more messages
                    Console.WriteLine("----------\n7. Still more messages. Issue another pull with batch size more than number of messages.");
                    sub.PullExpiresIn(10, 1200);
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 5 total messages, we received: " + messages.Count);

                    // 8. we got them all
                    Console.WriteLine("----------\n8. No messages left.");
                    sub.PullExpiresIn(10, 1200);
                    messages = JsUtils.ReadMessagesAck(sub, timeout: 2000);
                    Console.WriteLine("We should have received 0 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);
            }
        }
Esempio n. 9
0
        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 subjectNoAck = helper.Subject + "noack";
            string subjectAck   = helper.Subject + "ack";
            string deliverNoAck = helper.DeliverSubject + "noack";
            string deliverAck   = helper.DeliverSubject + "ack";

            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, subjectNoAck, subjectAck);

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

                    // The server uses the delivery subject as both an inbox for a JetStream subscription
                    // and as a core nats messages subject.
                    // BUT BE CAREFUL. THIS IS STILL A JETSTREAM SUBJECT AND ALL MESSAGES
                    // ADHERE TO THE ACK POLICY

                    // NoAck 1. Set up the noAck consumer / deliver subject configuration
                    ConsumerConfiguration cc = ConsumerConfiguration.Builder()
                                               .WithAckPolicy(AckPolicy.None)
                                               .WithAckWait(1000)
                                               .Build();

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

                    // NoAck 2. Set up the JetStream and core subscriptions
                    //          Notice the JetStream subscribes to the real subject
                    //          and the core subscribes to the delivery subject
                    //          Order matters, you must do the JetStream subscribe first
                    //          But you also must make sure the core sub is made
                    //          before messages are published
                    IJetStreamPushSyncSubscription jsSub = js.PushSubscribeSync(subjectNoAck, pso);
                    c.Flush(5000);
                    ISyncSubscription coreSub = c.SubscribeSync(deliverNoAck);

                    // NoAck 3. JsUtils.Publish to the real subject
                    JsUtils.Publish(js, subjectNoAck, "A", 1);

                    // NoAck 4. Read the message with the js no ack subscription. No need to ack
                    Msg msg = jsSub.NextMessage(1000);
                    PrintMessage("\nNoAck 4. Read w/JetStream sub", msg);

                    // NoAck 5. Read the message with the core subscription on the
                    //          no ack deliver subject. Since this message is a JetStream
                    //          message we could ack. But we don't have to since the consumer
                    //          was setup as AckPolicy None
                    msg = coreSub.NextMessage(1000);
                    PrintMessage("NoAck 5. Read w/core sub", msg);

                    // NoAck 6. Thread.Sleep longer than the ack wait period to check and make sure the
                    //     message is not replayed
                    Thread.Sleep(1100);

                    try
                    {
                        coreSub.NextMessage(1000);
                        Console.WriteLine("NoAck 6. NOPE! Should not have gotten here");
                    }
                    catch (NATSTimeoutException) // timeout means there are no messages available
                    {
                        Console.WriteLine("NoAck 6. Read w/core sub.\nAck Policy is none so no replay even though message was not Ack'd.\nThere was no message available.");
                    }

                    // Ack 1. Set up the Ack consumer / deliver subject configuration
                    cc = ConsumerConfiguration.Builder()
                         .WithAckPolicy(AckPolicy.Explicit)
                         .WithAckWait(1000)
                         .Build();

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

                    // Ack 2. Set up the JetStream and core subscriptions
                    jsSub = js.PushSubscribeSync(subjectAck, pso);
                    c.Flush(5000);
                    coreSub = c.SubscribeSync(deliverAck);

                    // Ack 3. JsUtils.Publish to the real subject
                    JsUtils.Publish(js, subjectAck, "B", 1);

                    // Ack 4. Read the message with the js no ack subscription. No need to ack
                    msg = jsSub.NextMessage(1000);
                    PrintMessage("\nAck 4. Read w/JetStream sub", msg);

                    // Ack 5. Read the message with the core subscription on the
                    //        ack deliver subject.
                    //        Even though it is read on a core subscription
                    //        it still is a JetStream message. Don't ack this time
                    msg = coreSub.NextMessage(1000);
                    PrintMessage("Ack 5. Read w/core sub", msg);

                    // Ack 6. Thread.Sleep longer than the ack wait period to check and
                    //        see that the message is re-delivered. Ack this time.
                    Thread.Sleep(1100);
                    msg = coreSub.NextMessage(1000);
                    msg.Ack();
                    PrintMessage("Ack 6. Read w/core sub.\nWasn't Ack'd after step 'Ack 5.' so message was replayed.", msg);

                    // Ack 7. Thread.Sleep longer than the ack wait period. The message
                    //        is not re-delivered this time
                    Thread.Sleep(1100);

                    try
                    {
                        coreSub.NextMessage(1000);
                        Console.WriteLine("Ack 7. NOPE! Should not have gotten here");
                    }
                    catch (NATSTimeoutException) // timeout means there are no messages available
                    {
                        Console.WriteLine("Ack 7. Read w/core sub.\nMessage received by core sub in step 'Ack 6.' was JetStream so it was Ack'd and therefore not replayed.\nThere was no message available.", msg);
                    }

                    // delete the stream since we are done with it.
                    jsm.DeleteStream(helper.Stream);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Esempio n. 10
0
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("JetStream Manage Streams", args, Usage)
                                    .DefaultStream("manage-stream-")
                                    .DefaultSubject("manage-subject-")
                                    .Build();

            string stream1  = helper.Stream + "1";
            string stream2  = helper.Stream + "2";
            string subject1 = helper.Subject + "1";
            string subject2 = helper.Subject + "2";
            string subject3 = helper.Subject + "3";
            string subject4 = helper.Subject + "4";

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

                    // we want to be able to completely create and delete the streams
                    // so don't want to work with existing streams
                    JsUtils.ExitIfStreamExists(jsm, stream1);
                    JsUtils.ExitIfStreamExists(jsm, stream2);

                    // 1. Create (add) a stream with a subject
                    Console.WriteLine("\n----------\n1. Configure And Add Stream 1");
                    StreamConfiguration streamConfig = StreamConfiguration.Builder()
                                                       .WithName(stream1)
                                                       .WithSubjects(subject1)
                                                       // .WithRetentionPolicy(...)
                                                       // .WithMaxConsumers(...)
                                                       // .WithMaxBytes(...)
                                                       // .WithMaxAge(...)
                                                       // .WithMaxMsgSize(...)
                                                       .WithStorageType(StorageType.Memory)
                                                       // .WithReplicas(...)
                                                       // .WithNoAck(...)
                                                       // .WithTemplateOwner(...)
                                                       // .WithDiscardPolicy(...)
                                                       .Build();

                    StreamInfo streamInfo = jsm.AddStream(streamConfig);
                    PrintUtils.PrintStreamInfo(streamInfo);

                    // 2. Update stream, in this case add a subject
                    //    Thre are very few properties that can actually
                    // -  StreamConfiguration is immutable once created
                    // -  but the builder can help with that.
                    Console.WriteLine("----------\n2. Update Stream 1");
                    streamConfig = StreamConfiguration.Builder(streamInfo.Config)
                                   .AddSubjects(subject2).Build();
                    streamInfo = jsm.UpdateStream(streamConfig);
                    PrintUtils.PrintStreamInfo(streamInfo);

                    // 3. Create (add) another stream with 2 subjects
                    Console.WriteLine("----------\n3. Configure And Add Stream 2");
                    streamConfig = StreamConfiguration.Builder()
                                   .WithName(stream2)
                                   .WithSubjects(subject3, subject4)
                                   .WithStorageType(StorageType.Memory)
                                   .Build();
                    streamInfo = jsm.AddStream(streamConfig);
                    PrintUtils.PrintStreamInfo(streamInfo);

                    // 4. Get information on streams
                    // 4.0 publish some message for more interesting stream state information
                    // -   SUBJECT1 is associated with STREAM1
                    // 4.1 getStreamInfo on a specific stream
                    // 4.2 get a list of all streams
                    // 4.3 get a list of StreamInfo's for all streams
                    Console.WriteLine("----------\n4.1 getStreamInfo");
                    JsUtils.Publish(c, subject1, 5);
                    streamInfo = jsm.GetStreamInfo(stream1);
                    PrintUtils.PrintStreamInfo(streamInfo);

                    Console.WriteLine("----------\n4.2 getStreamNames");
                    IList <String> streamNames = jsm.GetStreamNames();
                    PrintUtils.PrintObject(streamNames);

                    Console.WriteLine("----------\n4.3 getStreams");
                    IList <StreamInfo> streamInfos = jsm.GetStreams();
                    PrintUtils.PrintStreamInfoList(streamInfos);

                    // 5. Purge a stream of it's messages
                    Console.WriteLine("----------\n5. Purge stream");
                    PurgeResponse purgeResponse = jsm.PurgeStream(stream1);
                    PrintUtils.PrintObject(purgeResponse);

                    // 6. Delete the streams
                    // Subsequent calls to getStreamInfo, deleteStream or purgeStream
                    // will throw a JetStreamApiException "stream not found [10059]"
                    Console.WriteLine("----------\n6. Delete streams");
                    jsm.DeleteStream(stream1);
                    jsm.DeleteStream(stream2);

                    // 7. Try to delete the consumer again and get the exception
                    Console.WriteLine("----------\n7. Delete stream again");
                    try
                    {
                        jsm.DeleteStream(stream1);
                    }
                    catch (NATSJetStreamException e)
                    {
                        Console.WriteLine($"Exception was: '{e.ErrorDescription}'");
                    }

                    Console.WriteLine("----------\n");
                }
            }
            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);
            }
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("JetStream Publish With Options Use Cases", args, Usage)
                                    .DefaultStream("pubopts-stream")
                                    .DefaultSubject("pubopts-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);

                    // get a regular context
                    IJetStream js = c.CreateJetStreamContext();

                    PublishOptions.PublishOptionsBuilder builder = PublishOptions.Builder()
                                                                   .WithExpectedStream(helper.Stream)
                                                                   .WithMessageId("mid1");

                    PublishAck pa = js.Publish(helper.Subject, Encoding.ASCII.GetBytes("message1"), builder.Build());
                    Console.WriteLine("Published message on subject {0}, stream {1}, seqno {2}.",
                                      helper.Subject, pa.Stream, pa.Seq);

                    // IMPORTANT!
                    // You can reuse the builder in 2 ways.
                    // 1. Manually set a field to null or to DefaultLastSequence if you want to clear it out.
                    // 2. Use the clearExpected method to clear the expectedLastId, expectedLastSequence and messageId fields

                    // Manual re-use 1. Clearing some fields
                    builder
                    .WithExpectedLastMsgId("mid1")
                    .WithExpectedLastSequence(PublishOptions.DefaultLastSequence)
                    .WithMessageId(null);
                    pa = js.Publish(helper.Subject, Encoding.ASCII.GetBytes("message2"), builder.Build());
                    Console.WriteLine("Published message on subject {0}, stream {1}, seqno {2}.",
                                      helper.Subject, pa.Stream, pa.Seq);

                    // Manual re-use 2. Setting all the expected fields again
                    builder
                    .WithExpectedLastMsgId(null)
                    .WithExpectedLastSequence(PublishOptions.DefaultLastSequence)
                    .WithMessageId("mid3");
                    pa = js.Publish(helper.Subject, Encoding.ASCII.GetBytes("message3"), builder.Build());
                    Console.WriteLine("Published message on subject {0}, stream {1}, seqno {2}.",
                                      helper.Subject, pa.Stream, pa.Seq);

                    // reuse() method clears all the fields, then we set some fields.
                    builder.ClearExpected()
                    .WithExpectedLastSequence(pa.Seq)
                    .WithMessageId("mid4");
                    pa = js.Publish(helper.Subject, Encoding.ASCII.GetBytes("message4"), builder.Build());
                    Console.WriteLine("Published message on subject {0}, stream {1}, seqno {2}.",
                                      helper.Subject, pa.Stream, pa.Seq);

                    // exception when the expected stream does not match [10060]
                    try
                    {
                        PublishOptions errOpts = PublishOptions.Builder().WithExpectedStream("wrongStream").Build();
                        js.Publish(helper.Subject, Encoding.ASCII.GetBytes("ex1"), errOpts);
                    }
                    catch (NATSJetStreamException e)
                    {
                        Console.WriteLine($"Exception was: '{e.ErrorDescription}'");
                    }

                    // exception with wrong last msg ID [10070]
                    try
                    {
                        PublishOptions errOpts = PublishOptions.Builder().WithExpectedLastMsgId("wrongId").Build();
                        js.Publish(helper.Subject, Encoding.ASCII.GetBytes("ex2"), errOpts);
                    }
                    catch (NATSJetStreamException e)
                    {
                        Console.WriteLine($"Exception was: '{e.ErrorDescription}'");
                    }

                    // exception with wrong last sequence wrong last sequence: 4 [10071]
                    try
                    {
                        PublishOptions errOpts = PublishOptions.Builder().WithExpectedLastSequence(999).Build();
                        js.Publish(helper.Subject, Encoding.ASCII.GetBytes("ex3"), errOpts);
                    }
                    catch (NATSJetStreamException e)
                    {
                        Console.WriteLine($"Exception was: '{e.ErrorDescription}'");
                    }

                    // delete the stream since we are done with it.
                    jsm.DeleteStream(helper.Stream);
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
Esempio n. 13
0
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("JetStream Manage Consumers", args, Usage)
                                    .DefaultStream("mcon-stream")
                                    .DefaultSubject("mcon-subject")
                                    .DefaultDurable("mcon-durable-")
                                    .Build();

            try
            {
                string durable1 = helper.Durable + "1";
                string durable2 = helper.Durable + "2";

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

                    // 1. Add Consumers
                    Console.WriteLine("----------\n1. Configure And Add Consumers");
                    ConsumerConfiguration cc = ConsumerConfiguration.Builder()
                                               .WithDurable(durable1) // durable name is required when creating consumers
                                               .Build();
                    ConsumerInfo ci = jsm.AddOrUpdateConsumer(helper.Stream, cc);
                    PrintConsumerInfo(ci);

                    cc = ConsumerConfiguration.Builder()
                         .WithDurable(durable2)
                         .Build();
                    ci = jsm.AddOrUpdateConsumer(helper.Stream, cc);
                    PrintObject(ci);

                    // 2. get a list of ConsumerInfo's for all consumers
                    Console.WriteLine("\n----------\n2. getConsumers");
                    IList <ConsumerInfo> consumers = jsm.GetConsumers(helper.Stream);
                    PrintConsumerInfoList(consumers);

                    // 3. get a list of all consumers
                    Console.WriteLine("\n----------\n3. getConsumerNames");
                    IList <string> consumerNames = jsm.GetConsumerNames(helper.Stream);
                    Console.WriteLine("Consumer Names: " + String.Join(",", consumerNames));

                    // 4. Delete a consumer, then list them again
                    // Subsequent calls to deleteStream will throw a
                    // NATSJetStreamException [10014]
                    Console.WriteLine("\n----------\n4. Delete a consumer");
                    jsm.DeleteConsumer(helper.Stream, durable1);
                    consumerNames = jsm.GetConsumerNames(helper.Stream);
                    Console.WriteLine("Consumer Names: " + String.Join(",", consumerNames));

                    // 5. Try to delete the consumer again and get the exception
                    Console.WriteLine("\n----------\n5. Delete consumer again");
                    try
                    {
                        jsm.DeleteConsumer(helper.Stream, durable1);
                    }
                    catch (NATSJetStreamException e)
                    {
                        Console.WriteLine($"Exception was: '{e.ErrorDescription}'");
                    }

                    Console.WriteLine("\n----------");

                    // 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("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("Pull Subscription using primitive Expires In", args, Usage)
                                    .DefaultStream("expires-in-stream")
                                    .DefaultSubject("expires-in-subject")
                                    .DefaultDurable("expires-in-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, "expires-in-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.PullExpiresIn(10, 1000);
                        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);
            }
        }
Esempio n. 16
0
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("JetStream Publish Async", args, Usage)
                                    .DefaultStream("example-stream")
                                    .DefaultSubject("example-subject")
                                    .DefaultPayload("Hello")
                                    .DefaultCount(10)
                                    .Build();

            try
            {
                using (IConnection c = new ConnectionFactory().CreateConnection(helper.MakeOptions()))
                {
                    // Use the utility to create a stream stored in memory.
                    JsUtils.CreateStreamOrUpdateSubjects(c, helper.Stream, helper.Subject);

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

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

                    int stop = helper.Count < 2 ? 2 : helper.Count + 1;
                    for (int x = 1; x < stop; x++)
                    {
                        // make unique message data if you want more than 1 message
                        byte[] data = helper.Count < 2
                            ? Encoding.UTF8.GetBytes(helper.Payload)
                            : Encoding.UTF8.GetBytes(helper.Payload + "-" + x);

                        // Publish a message and print the results of the publish acknowledgement.
                        Msg msg = new Msg(helper.Subject, null, helper.Header, data);

                        // We'll use the defaults for this simple example, but there are options
                        // to constrain publishing to certain streams, expect sequence numbers and
                        // more. See the JetStreamPublishWithOptionsUseCases example for details.
                        // An exception will be thrown if there is a failure.
                        tasks.Add(js.PublishAsync(msg));

                        while (tasks.Count > 0)
                        {
                            Task <PublishAck> task = tasks[0];
                            tasks.RemoveAt(0);

                            if (task.IsCompleted)
                            {
                                try
                                {
                                    PublishAck pa = task.Result;
                                    Console.WriteLine("Published message {0} on subject {1}, stream {2}, seqno {3}.",
                                                      Encoding.UTF8.GetString(data), helper.Subject, pa.Stream, pa.Seq);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("Publish Failed: " + e);
                                }
                            }
                            else
                            {
                                // re queue so will be checked for completed again
                                tasks.Add(task);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                helper.ReportException(ex);
            }
        }
        public static void Main(string[] args)
        {
            ArgumentHelper helper = new ArgumentHelperBuilder("Pull Subscription using primitive No Wait, Use Cases", args, Usage)
                                    .DefaultStream("nowait-uc-stream")
                                    .DefaultSubject("nowait-uc-subject")
                                    .DefaultDurable("nowait-uc-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 DO NOT start the pull, no wait works differently than regular pull.
                    //     With no wait, we have to start the pull the first time and every time the
                    //     batch size is exhausted or no waits out.
                    // 0.3 Flush outgoing communication with/to the server, useful when app is both publishing and subscribing.
                    Console.WriteLine("\n----------\n0. Initialize the subscription and pull.");
                    IJetStreamPullSubscription sub = js.PullSubscribe(helper.Subject, pullOptions);
                    c.Flush(1000);

                    // 1. Start the pull, but there are no messages yet.
                    // -  Read the messages
                    // -  Since there are less than the batch size, we get them all (0)
                    Console.WriteLine("----------\n1. There are no messages yet");
                    sub.PullNoWait(10);
                    IList <Msg> messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 0 total messages, we received: " + messages.Count);

                    // 2. Publish 10 messages
                    // -  Start the pull
                    // -  Read the messages
                    // -  Since there are exactly the batch size we get them all
                    Console.WriteLine("----------\n2. Publish 10 which satisfies the batch");
                    JsUtils.Publish(js, helper.Subject, "A", 10);
                    sub.PullNoWait(10);
                    messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count);

                    // 3. Publish 20 messages
                    // -  Start the pull
                    // -  Read the messages
                    Console.WriteLine("----------\n3. Publish 20 which is larger than the batch size.");
                    JsUtils.Publish(js, helper.Subject, "B", 20);
                    sub.PullNoWait(10);
                    messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count);

                    // 4. There are still messages left from the last
                    // -  Start the pull
                    // -  Read the messages
                    Console.WriteLine("----------\n4. Get the rest of the publish.");
                    sub.PullNoWait(10);
                    messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count);

                    // 5. Publish 5 messages
                    // -  Start the pull
                    // -  Read the messages
                    Console.WriteLine("----------\n5. Publish 5 which is less than batch size.");
                    JsUtils.Publish(js, helper.Subject, "C", 5);
                    sub.PullNoWait(10);
                    messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 5 total messages, we received: " + messages.Count);

                    // 6. Publish 14 messages
                    // -  Start the pull
                    // -  Read the messages
                    // -  we do NOT get a nowait status message if there are more or equals messages than the batch
                    Console.WriteLine("----------\n6. Publish 14 which is more than the batch size.");
                    JsUtils.Publish(js, helper.Subject, "D", 14);
                    sub.PullNoWait(10);
                    messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 10 total messages, we received: " + messages.Count);

                    // 7. There are 4 messages left
                    // -  Start the pull
                    // -  Read the messages
                    // -  Since there are less than batch size the last message we get will be a status 404 message.
                    Console.WriteLine("----------\n7. There are 4 messages left, which is less than the batch size.");
                    sub.PullNoWait(10);
                    messages = JsUtils.ReadMessagesAck(sub);
                    Console.WriteLine("We should have received 4 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);
            }
        }
        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);
            }
        }
Esempio n. 19
0
        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);
            }
        }