private void AssertContainsPublishAck(PublishAck pa, IList <ulong> seqnos) { Assert.Equal(STREAM, pa.Stream); Assert.False(pa.Duplicate); Assert.True(seqnos.Contains(pa.Seq)); seqnos.Remove(pa.Seq); }
public void TestPublishNoAck() { Context.RunInJsServer(c => { CreateDefaultTestStream(c); JetStreamOptions jso = JetStreamOptions.Builder().WithPublishNoAck(true).Build(); IJetStream js = c.CreateJetStreamContext(jso); string data1 = "noackdata1"; string data2 = "noackdata2"; PublishAck pa = js.Publish(SUBJECT, Encoding.ASCII.GetBytes(data1)); Assert.Null(pa); Task <PublishAck> task = js.PublishAsync(SUBJECT, Encoding.ASCII.GetBytes(data2)); Assert.Null(task.Result); IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT); Msg m = sub.NextMessage(DefaultTimeout); Assert.NotNull(m); Assert.Equal(data1, Encoding.ASCII.GetString(m.Data)); m = sub.NextMessage(DefaultTimeout); Assert.NotNull(m); Assert.Equal(data2, Encoding.ASCII.GetString(m.Data)); }); }
public void TestPublishAckJson() { string json = "{\"stream\":\"sname\", \"seq\":42, \"duplicate\":false}"; PublishAck pa = new PublishAck(json); Assert.Equal("sname", pa.Stream); Assert.Equal(42U, pa.Seq); Assert.False(pa.Duplicate); }
public void TestJetStreamPublishDefaultOptions() { Context.RunInJsServer(c => { CreateDefaultTestStream(c); IJetStream js = c.CreateJetStreamContext(); PublishAck ack = JsPublish(js); Assert.Equal(1U, ack.Seq); }); }
public void IsValidAck() { String json = "{\"stream\":\"test-stream\",\"seq\":42,\"domain\":\"test-domain\", \"duplicate\" : true }"; PublishAck ack = new PublishAck(json); Assert.Equal("test-stream", ack.Stream); Assert.Equal("test-domain", ack.Domain); Assert.Equal(42ul, ack.Seq); Assert.True(ack.Duplicate); }
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); } }
public async Task when_writing_publish_ack_packet_then_succeeds(string jsonPath, string packetPath) { jsonPath = Path.Combine(Environment.CurrentDirectory, jsonPath); packetPath = Path.Combine(Environment.CurrentDirectory, packetPath); byte[] expectedPacket = Packet.ReadAllBytes(packetPath); FlowPacketFormatter <PublishAck> formatter = new FlowPacketFormatter <PublishAck>(MqttPacketType.PublishAck, id => new PublishAck(id)); PublishAck publishAck = Packet.ReadPacket <PublishAck>(jsonPath); byte[] result = await formatter.FormatAsync(publishAck); expectedPacket.Should().BeEquivalentTo(result); }
public void TestPublishVarieties() { Context.RunInJsServer(c => { CreateDefaultTestStream(c); IJetStream js = c.CreateJetStreamContext(); PublishAck pa = js.Publish(SUBJECT, DataBytes(1)); AssertPublishAck(pa, 1); Msg msg = new Msg(SUBJECT, DataBytes(2)); pa = js.Publish(msg); AssertPublishAck(pa, 2); PublishOptions po = PublishOptions.Builder().Build(); pa = js.Publish(SUBJECT, DataBytes(3), po); AssertPublishAck(pa, 3); msg = new Msg(SUBJECT, DataBytes(4)); pa = js.Publish(msg, po); AssertPublishAck(pa, 4); pa = js.Publish(SUBJECT, null); AssertPublishAck(pa, 5); msg = new Msg(SUBJECT); pa = js.Publish(msg); AssertPublishAck(pa, 6); pa = js.Publish(SUBJECT, null, po); AssertPublishAck(pa, 7); msg = new Msg(SUBJECT); pa = js.Publish(msg, po); AssertPublishAck(pa, 8); IJetStreamPushSyncSubscription s = js.PushSubscribeSync(SUBJECT); AssertNextMessage(s, Data(1)); AssertNextMessage(s, Data(2)); AssertNextMessage(s, Data(3)); AssertNextMessage(s, Data(4)); AssertNextMessage(s, null); // 5 AssertNextMessage(s, null); // 6 AssertNextMessage(s, null); // 7 AssertNextMessage(s, null); // 8 // bad subject Assert.Throws <NATSNoRespondersException>(() => js.Publish(Subject(999), null)); }); }
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); } }
public void TestDeliveryPolicy() { Context.RunInJsServer(c => { IJetStreamManagement jsm = c.CreateJetStreamManagementContext(); IJetStream js = c.CreateJetStreamContext(); CreateMemoryStream(jsm, STREAM, SUBJECT_STAR); string subjectA = SubjectDot("A"); string subjectB = SubjectDot("B"); js.Publish(subjectA, DataBytes(1)); js.Publish(subjectA, DataBytes(2)); Thread.Sleep(1500); js.Publish(subjectA, DataBytes(3)); js.Publish(subjectB, DataBytes(91)); js.Publish(subjectB, DataBytes(92)); // DeliverPolicy.All PushSubscribeOptions pso = PushSubscribeOptions.Builder() .WithConfiguration(ConsumerConfiguration.Builder().WithDeliverPolicy(DeliverPolicy.All).Build()) .Build(); IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(subjectA, pso); Msg m1 = sub.NextMessage(1000); AssertMessage(m1, 1); Msg m2 = sub.NextMessage(1000); AssertMessage(m2, 2); Msg m3 = sub.NextMessage(1000); AssertMessage(m3, 3); // DeliverPolicy.Last pso = PushSubscribeOptions.Builder() .WithConfiguration(ConsumerConfiguration.Builder().WithDeliverPolicy(DeliverPolicy.Last).Build()) .Build(); sub = js.PushSubscribeSync(subjectA, pso); Msg m = sub.NextMessage(1000); AssertMessage(m, 3); AssertNoMoreMessages(sub); // DeliverPolicy.New - No new messages between subscribe and next message pso = PushSubscribeOptions.Builder() .WithConfiguration(ConsumerConfiguration.Builder().WithDeliverPolicy(DeliverPolicy.New).Build()) .Build(); sub = js.PushSubscribeSync(subjectA, pso); AssertNoMoreMessages(sub); // DeliverPolicy.New - New message between subscribe and next message sub = js.PushSubscribeSync(subjectA, pso); js.Publish(subjectA, DataBytes(4)); m = sub.NextMessage(1000); AssertMessage(m, 4); // DeliverPolicy.ByStartSequence pso = PushSubscribeOptions.Builder() .WithConfiguration(ConsumerConfiguration.Builder() .WithDeliverPolicy(DeliverPolicy.ByStartSequence) .WithStartSequence(3) .Build()) .Build(); sub = js.PushSubscribeSync(subjectA, pso); m = sub.NextMessage(1000); AssertMessage(m, 3); m = sub.NextMessage(1000); AssertMessage(m, 4); // DeliverPolicy.ByStartTime pso = PushSubscribeOptions.Builder() .WithConfiguration(ConsumerConfiguration.Builder() .WithDeliverPolicy(DeliverPolicy.ByStartTime) .WithStartTime(m3.MetaData.Timestamp.AddSeconds(-1)) .Build()) .Build(); sub = js.PushSubscribeSync(subjectA, pso); m = sub.NextMessage(1000); AssertMessage(m, 3); m = sub.NextMessage(1000); AssertMessage(m, 4); // DeliverPolicy.LastPerSubject pso = PushSubscribeOptions.Builder() .WithConfiguration(ConsumerConfiguration.Builder() .WithDeliverPolicy(DeliverPolicy.LastPerSubject) .WithFilterSubject(subjectA) .Build()) .Build(); sub = js.PushSubscribeSync(subjectA, pso); m = sub.NextMessage(1000); AssertMessage(m, 4); // DeliverPolicy.ByStartSequence with a deleted record PublishAck pa4 = js.Publish(subjectA, DataBytes(4)); PublishAck pa5 = js.Publish(subjectA, DataBytes(5)); js.Publish(subjectA, DataBytes(6)); jsm.DeleteMessage(STREAM, pa4.Seq); jsm.DeleteMessage(STREAM, pa5.Seq); pso = ConsumerConfiguration.Builder() .WithDeliverPolicy(DeliverPolicy.ByStartSequence) .WithStartSequence(pa4.Seq) .BuildPushSubscribeOptions(); sub = js.PushSubscribeSync(subjectA, pso); m = sub.NextMessage(1000); AssertMessage(m, 6); }); }
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("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); } }
private void AssertPublishAck(PublishAck pa, ulong seqno) { Assert.Equal(STREAM, pa.Stream); Assert.Equal(seqno, pa.Seq); Assert.False(pa.Duplicate); }
public void TestPublishExpectations() { Context.RunInJsServer(c => { CreateMemoryStream(c, STREAM, Subject(1), Subject(2)); IJetStream js = c.CreateJetStreamContext(); PublishOptions po = PublishOptions.Builder() .WithExpectedStream(STREAM) .WithMessageId(MessageId(1)) .Build(); PublishAck pa = js.Publish(Subject(1), DataBytes(1), po); AssertPublishAck(pa, 1); po = PublishOptions.Builder() .WithExpectedLastMsgId(MessageId(1)) .WithMessageId(MessageId(2)) .Build(); pa = js.Publish(Subject(1), DataBytes(2), po); AssertPublishAck(pa, 2); po = PublishOptions.Builder() .WithExpectedLastSequence(2) .WithMessageId(MessageId(3)) .Build(); pa = js.Publish(Subject(1), DataBytes(3), po); AssertPublishAck(pa, 3); po = PublishOptions.Builder() .WithExpectedLastSequence(3) .WithMessageId(MessageId(4)) .Build(); pa = js.Publish(Subject(2), DataBytes(4), po); AssertPublishAck(pa, 4); po = PublishOptions.Builder() .WithExpectedLastSubjectSequence(3) .WithMessageId(MessageId(5)) .Build(); pa = js.Publish(Subject(1), DataBytes(5), po); AssertPublishAck(pa, 5); po = PublishOptions.Builder() .WithExpectedLastSubjectSequence(4) .WithMessageId(MessageId(6)) .Build(); pa = js.Publish(Subject(2), DataBytes(6), po); AssertPublishAck(pa, 6); PublishOptions po1 = PublishOptions.Builder().WithExpectedStream(Stream(999)).Build(); Assert.Throws <NATSJetStreamException>(() => js.Publish(Subject(1), DataBytes(999), po1)); PublishOptions po2 = PublishOptions.Builder().WithExpectedLastMsgId(MessageId(999)).Build(); Assert.Throws <NATSJetStreamException>(() => js.Publish(Subject(1), DataBytes(999), po2)); PublishOptions po3 = PublishOptions.Builder().WithExpectedLastSequence(999).Build(); Assert.Throws <NATSJetStreamException>(() => js.Publish(Subject(1), DataBytes(999), po3)); PublishOptions po4 = PublishOptions.Builder().WithExpectedLastSubjectSequence(999).Build(); Assert.Throws <NATSJetStreamException>(() => js.Publish(Subject(1), DataBytes(999), po4)); }); }
public void TestGetStreamInfo() { Context.RunInJsServer(c => { IJetStreamManagement jsm = c.CreateJetStreamManagementContext(); Assert.Throws <NATSJetStreamException>(() => jsm.GetStreamInfo(STREAM)); String[] subjects = new String[6]; for (int x = 0; x < 5; x++) { subjects[x] = Subject(x); } subjects[5] = "foo.>"; CreateMemoryStream(jsm, STREAM, subjects); IList <PublishAck> packs = new List <PublishAck>(); IJetStream js = c.CreateJetStreamContext(); for (int x = 0; x < 5; x++) { JsPublish(js, Subject(x), x + 1); PublishAck pa = JsPublish(js, Subject(x), Data(x + 2)); packs.Add(pa); jsm.DeleteMessage(STREAM, pa.Seq); } JsPublish(js, "foo.bar", 6); StreamInfo si = jsm.GetStreamInfo(STREAM); Assert.Equal(STREAM, si.Config.Name); Assert.Equal(6, si.State.SubjectCount); Assert.Null(si.State.Subjects); Assert.Equal(5, si.State.DeletedCount); Assert.Empty(si.State.Deleted); si = jsm.GetStreamInfo(STREAM, StreamInfoOptions.Builder() .WithAllSubjects() .WithDeletedDetails() .Build()); Assert.Equal(STREAM, si.Config.Name); Assert.Equal(6, si.State.SubjectCount); IList <Subject> list = si.State.Subjects; Assert.NotNull(list); Assert.Equal(6, list.Count); Assert.Equal(5, si.State.DeletedCount); Assert.Equal(5, si.State.Deleted.Count); Dictionary <string, Subject> map = new Dictionary <string, Subject>(); foreach (Subject su in list) { map[su.Name] = su; } for (int x = 0; x < 5; x++) { Subject subj = map[Subject(x)]; Assert.NotNull(subj); Assert.Equal(x + 1, subj.Count); } Subject s = map["foo.bar"]; Assert.NotNull(s); Assert.Equal(6, s.Count); foreach (PublishAck pa in packs) { Assert.True(si.State.Deleted.Contains(pa.Seq)); } }); }