public void TestJetStreamSubscribeErrors() { Context.RunInJsServer(c => { IJetStream js = c.CreateJetStreamContext(); // stream not found PushSubscribeOptions psoInvalidStream = PushSubscribeOptions.Builder().WithStream(STREAM).Build(); Assert.Throws <NATSJetStreamException>(() => js.PushSubscribeSync(SUBJECT, psoInvalidStream)); void AssertThrowsForSubject(Func <object> testCode) { ArgumentException ae = Assert.Throws <ArgumentException>(testCode); Assert.StartsWith("Subject", ae.Message); } void AssertThrowsForQueue(Func <object> testCode) { ArgumentException ae = Assert.Throws <ArgumentException>(testCode); Assert.StartsWith("Queue", ae.Message); } void AssertThrowsForHandler(Func <object> testCode) { ArgumentNullException ae = Assert.Throws <ArgumentNullException>(testCode); Assert.Equal("Handler", ae.ParamName); } // subject AssertThrowsForSubject(() => js.PushSubscribeSync(HasSpace)); AssertThrowsForSubject(() => js.PushSubscribeSync(null, (PushSubscribeOptions)null)); AssertThrowsForSubject(() => js.PushSubscribeSync(HasSpace, Plain)); AssertThrowsForSubject(() => js.PushSubscribeSync(null, Plain, null)); AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, null, false)); AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, null, false, null)); AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, Plain, null, false)); AssertThrowsForSubject(() => js.PushSubscribeAsync(HasSpace, Plain, null, false, null)); // queue AssertThrowsForQueue(() => js.PushSubscribeSync(Plain, HasSpace)); AssertThrowsForQueue(() => js.PushSubscribeSync(Plain, HasSpace, null)); AssertThrowsForQueue(() => js.PushSubscribeAsync(Plain, HasSpace, null, false)); AssertThrowsForQueue(() => js.PushSubscribeAsync(Plain, HasSpace, null, false, null)); // handler AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, null, false)); AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, null, false, null)); AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, Plain, null, false)); AssertThrowsForHandler(() => js.PushSubscribeAsync(Plain, Plain, null, false, null)); }); }
public void TestHandlerSub() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // publish some messages JsPublish(js, SUBJECT, 10); CountdownEvent latch = new CountdownEvent(10); int received = 0; void TestHandler(object sender, MsgHandlerEventArgs args) { received++; args.Message.Ack(); latch.Signal(); } // Subscribe using the handler js.PushSubscribeAsync(SUBJECT, TestHandler, false); // Wait for messages to arrive using the countdown latch. latch.Wait(); Assert.Equal(10, received); }); }
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); } }
public void TestOrderedConsumerAsync() { Console.SetOut(new ConsoleWriter(output)); Context.RunInJsServer(c => { // Setup IJetStream js = c.CreateJetStreamContext(); string subject = Subject(222); CreateMemoryStream(c, Stream(222), subject); // Get this in place before any subscriptions are made JetStream.PushMessageManagerFactoryImpl = (conn, so, cc, queueMode, syncMode) => new OrderedTestDropSimulator(conn, so, cc, queueMode, syncMode); // The options will be used in various ways PushSubscribeOptions pso = PushSubscribeOptions.Builder().WithOrdered(true).Build(); // Test queue exception void DummyTestHandler(object sender, MsgHandlerEventArgs args) { } NATSJetStreamClientException e = Assert.Throws <NATSJetStreamClientException>(() => js.PushSubscribeAsync(subject, QUEUE, DummyTestHandler, false, pso)); Assert.Contains(JsSubOrderedNotAllowOnQueues.Id, e.Message); // Setup async subscription CountdownEvent latch = new CountdownEvent(6); InterlockedInt received = new InterlockedInt(); InterlockedLong[] ssFlags = new InterlockedLong[6]; InterlockedLong[] csFlags = new InterlockedLong[6]; void TestHandler(object sender, MsgHandlerEventArgs args) { int i = received.Increment() - 1; ssFlags[i] = new InterlockedLong((long)args.msg.MetaData.StreamSequence); csFlags[i] = new InterlockedLong((long)args.msg.MetaData.ConsumerSequence); latch.Signal(); } js.PushSubscribeAsync(subject, TestHandler, false, pso); Thread.Sleep(1000); // Published messages will be intercepted by the OrderedTestDropSimulator JsPublish(js, subject, 101, 6); // wait for the messages latch.Wait(); // Loop through the messages to make sure I get stream sequence 1 to 6 ulong expectedStreamSeq = 1; while (expectedStreamSeq <= 6) { int idx = (int)expectedStreamSeq - 1; Assert.Equal(expectedStreamSeq, (ulong)ssFlags[idx].Read()); Assert.Equal(ExpectedConSeqNums[idx], (ulong)csFlags[idx].Read()); ++expectedStreamSeq; } }); }
public void TestJetStreamPushDurableSubAsync() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); IJetStreamManagement jsm = c.CreateJetStreamManagementContext(); // publish some messages JsPublish(js, SUBJECT, 5); // Build our subscription options normally PushSubscribeOptions optionsSync1 = PushSubscribeOptions.Builder() .WithDurable(Durable(1)) .WithDeliverSubject(Deliver(1)) .Build(); _testPushDurableSubAsync(js, h => js.PushSubscribeAsync(SUBJECT, h, false, optionsSync1)); // bind long form jsm.AddOrUpdateConsumer(STREAM, ConsumerConfiguration.Builder() .WithDurable(Durable(2)) .WithDeliverSubject(Deliver(2)) .Build()); PushSubscribeOptions options2 = PushSubscribeOptions.Builder() .WithStream(STREAM) .WithDurable(Durable(2)) .WithBind(true) .Build(); _testPushDurableSubAsync(js, h => js.PushSubscribeAsync(null, h, false, options2)); // bind short form jsm.AddOrUpdateConsumer(STREAM, ConsumerConfiguration.Builder() .WithDurable(Durable(3)) .WithDeliverSubject(Deliver(3)) .Build()); PushSubscribeOptions options3 = PushSubscribeOptions.BindTo(STREAM, Durable(3)); _testPushDurableSubAsync(js, h => js.PushSubscribeAsync(null, h, false, options3)); }); }
public void TestDontAutoAckIfUserAcks() { string mockAckReply = "mock-ack-reply."; Context.RunInJsServer(c => { CreateMemoryStream(c, STREAM, SUBJECT, mockAckReply + "*"); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // publish some messages JsPublish(js, SUBJECT, 2); // 1. auto ack true CountdownEvent latch = new CountdownEvent(2); bool flag = true; // create our message handler, does not ack void Handler(object sender, MsgHandlerEventArgs args) { if (flag) { args.Message.Reply = mockAckReply + "user"; args.Message.Ack(); flag = false; } args.Message.Reply = mockAckReply + "system"; latch.Signal(); } // subscribe using the handler, auto ack true js.PushSubscribeAsync(SUBJECT, Handler, true); // wait for messages to arrive using the countdown latch. latch.Wait(); IJetStreamPushSyncSubscription ssub = js.PushSubscribeSync(mockAckReply + "*"); Msg m = ssub.NextMessage(1000); Assert.Equal(mockAckReply + "user", m.Subject); m = ssub.NextMessage(1000); Assert.Equal(mockAckReply + "system", m.Subject); }); }
public void TestJetStreamSubscribe() { Context.RunInJsServer(c => { IJetStream js = c.CreateJetStreamContext(); IJetStreamManagement jsm = c.CreateJetStreamManagementContext(); CreateDefaultTestStream(jsm); JsPublish(js); // default ephemeral subscription. IJetStreamPushSyncSubscription s = js.PushSubscribeSync(SUBJECT); Msg m = s.NextMessage(DefaultTimeout); Assert.NotNull(m); Assert.Equal(DATA, Encoding.UTF8.GetString(m.Data)); IList <String> names = jsm.GetConsumerNames(STREAM); Assert.Equal(1, names.Count); // default subscribe options // ephemeral subscription. s = js.PushSubscribeSync(SUBJECT, PushSubscribeOptions.Builder().Build()); m = s.NextMessage(DefaultTimeout); Assert.NotNull(m); Assert.Equal(DATA, Encoding.UTF8.GetString(m.Data)); names = jsm.GetConsumerNames(STREAM); Assert.Equal(2, names.Count); // set the stream PushSubscribeOptions pso = PushSubscribeOptions.Builder() .WithStream(STREAM).WithDurable(DURABLE).Build(); s = js.PushSubscribeSync(SUBJECT, pso); m = s.NextMessage(DefaultTimeout); Assert.NotNull(m); Assert.Equal(DATA, Encoding.UTF8.GetString(m.Data)); names = jsm.GetConsumerNames(STREAM); Assert.Equal(3, names.Count); // coverage js.PushSubscribeSync(SUBJECT); js.PushSubscribeSync(SUBJECT, (PushSubscribeOptions)null); js.PushSubscribeSync(SUBJECT, QUEUE, null); js.PushSubscribeAsync(SUBJECT, (o, a) => {}, false); js.PushSubscribeAsync(SUBJECT, (o, a) => {}, false, null); js.PushSubscribeAsync(SUBJECT, QUEUE, (o, a) => {}, false, null); // bind with w/o subject jsm.AddOrUpdateConsumer(STREAM, ConsumerConfiguration.Builder() .WithDurable(Durable(101)) .WithDeliverSubject(Deliver(101)) .Build()); PushSubscribeOptions psoBind = PushSubscribeOptions.BindTo(STREAM, Durable(101)); js.PushSubscribeSync(null, psoBind).Unsubscribe(); js.PushSubscribeSync("", psoBind).Unsubscribe(); js.PushSubscribeAsync(null, (o, a) => { }, false, psoBind).Unsubscribe(); js.PushSubscribeAsync("", (o, a) => { }, false, psoBind); jsm.AddOrUpdateConsumer(STREAM, ConsumerConfiguration.Builder() .WithDurable(Durable(102)) .WithDeliverSubject(Deliver(102)) .WithDeliverGroup(Queue(102)) .Build()); psoBind = PushSubscribeOptions.BindTo(STREAM, Durable(102)); js.PushSubscribeSync(null, Queue(102), psoBind).Unsubscribe(); js.PushSubscribeSync("", Queue(102), psoBind).Unsubscribe(); js.PushSubscribeAsync(null, Queue(102), (o, a) => { }, false, psoBind).Unsubscribe(); js.PushSubscribeAsync("", Queue(102), (o, a) => { }, false, psoBind); }); }
public void TestHandlerAutoAck() { Context.RunInJsServer(c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); // publish some messages JsPublish(js, SUBJECT, 10); // 1. auto ack true CountdownEvent latch1 = new CountdownEvent(10); int handlerReceived1 = 0; // create our message handler, does not ack void Handler1(object sender, MsgHandlerEventArgs args) { handlerReceived1++; latch1.Signal(); } // subscribe using the handler, auto ack true PushSubscribeOptions pso1 = PushSubscribeOptions.Builder() .WithDurable(Durable(1)).Build(); IJetStreamPushAsyncSubscription asub = js.PushSubscribeAsync(SUBJECT, Handler1, true, pso1); // wait for messages to arrive using the countdown latch. latch1.Wait(); Assert.Equal(10, handlerReceived1); asub.Unsubscribe(); // check that all the messages were read by the durable IJetStreamPushSyncSubscription ssub = js.PushSubscribeSync(SUBJECT, pso1); AssertNoMoreMessages(ssub); // 2. auto ack false CountdownEvent latch2 = new CountdownEvent(10); int handlerReceived2 = 0; // create our message handler, also does not ack void Handler2(object sender, MsgHandlerEventArgs args) { handlerReceived2++; latch2.Signal(); } // subscribe using the handler, auto ack false ConsumerConfiguration cc = ConsumerConfiguration.Builder().WithAckWait(500).Build(); PushSubscribeOptions pso2 = PushSubscribeOptions.Builder() .WithDurable(Durable(2)).WithConfiguration(cc).Build(); asub = js.PushSubscribeAsync(SUBJECT, Handler2, false, pso2); // wait for messages to arrive using the countdown latch. latch2.Wait(); Assert.Equal(10, handlerReceived2); Thread.Sleep(2000); // just give it time for the server to realize the messages are not ack'ed asub.Unsubscribe(); // check that we get all the messages again ssub = js.PushSubscribeSync(SUBJECT, pso2); Assert.Equal(10, ReadMessagesAck(ssub).Count); }); }
public void TestPushAsyncFlowControl() { InterlockedInt fcps = new InterlockedInt(); Action <Options> optionsModifier = opts => { opts.FlowControlProcessedEventHandler = (sender, args) => { fcps.Increment(); }; }; Context.RunInJsServer(new TestServerInfo(TestSeedPorts.AutoPort.Increment()), optionsModifier, c => { // create the stream. CreateDefaultTestStream(c); // Create our JetStream context. IJetStream js = c.CreateJetStreamContext(); byte[] data = new byte[8192]; int msgCount = 1000; for (int x = 100_000; x < msgCount + 100_000; x++) { byte[] fill = Encoding.ASCII.GetBytes("" + x); Array.Copy(fill, 0, data, 0, 6); js.Publish(new Msg(SUBJECT, data)); } InterlockedInt count = new InterlockedInt(); HashSet <string> set = new HashSet <string>(); CountdownEvent latch = new CountdownEvent(msgCount); // create our message handler, does not ack void Handler(object sender, MsgHandlerEventArgs args) { byte[] fill = new byte[6]; Array.Copy(args.Message.Data, 0, fill, 0, 6); string id = Encoding.ASCII.GetString(fill); if (set.Add(id)) { count.Increment(); } args.Message.Ack(); latch.Signal(); } // subscribe using the handler ConsumerConfiguration cc = ConsumerConfiguration.Builder().WithFlowControl(1000).Build(); PushSubscribeOptions pso = PushSubscribeOptions.Builder().WithConfiguration(cc).Build(); js.PushSubscribeAsync(SUBJECT, Handler, false, pso); // wait for messages to arrive using the countdown latch. latch.Wait(); Assert.Equal(msgCount, count.Read()); Assert.True(fcps.Read() > 0); }); }