Пример #1
0
        public void TestQueueSubWorkflow()
        {
            Context.RunInJsServer(c =>
            {
                // create the stream.
                CreateDefaultTestStream(c);

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

                // Setup the subscribers
                // - the PushSubscribeOptions can be re-used since all the subscribers are the same
                // - use a concurrent integer to track all the messages received
                // - have a list of subscribers and threads so I can track them
                PushSubscribeOptions pso              = PushSubscribeOptions.Builder().WithDurable(DURABLE).Build();
                InterlockedLong allReceived           = new InterlockedLong();
                IList <JsQueueSubscriber> subscribers = new List <JsQueueSubscriber>();
                IList <Thread> subThreads             = new List <Thread>();
                for (int id = 1; id <= 3; id++)
                {
                    // setup the subscription
                    IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(SUBJECT, QUEUE, pso);
                    // create and track the runnable
                    JsQueueSubscriber qs = new JsQueueSubscriber(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(DefaultTimeout); // flush outgoing communication with/to the server

                // create and start the publishing
                Thread pubThread = new Thread(new JsPublisher(js, 100).Run);
                pubThread.Start();

                // wait for all threads to finish
                pubThread.Join(5000);
                foreach (Thread t in subThreads)
                {
                    t.Join(5000);
                }

                ISet <string> uniqueDatas = new HashSet <string>();
                // count
                int count = 0;
                foreach (JsQueueSubscriber qs in subscribers)
                {
                    int r = qs.received;
                    Assert.True(r > 0);
                    count += r;
                    foreach (string s in qs.datas)
                    {
                        Assert.True(uniqueDatas.Add(s));
                    }
                }

                Assert.Equal(100, count);
            });
        }
Пример #2
0
        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;
                }
            });
        }
Пример #3
0
 public JsQueueSubscriber(int msgCount, IJetStream js, IJetStreamPushSyncSubscription sub, InterlockedLong allReceived)
 {
     this.msgCount    = msgCount;
     this.js          = js;
     this.sub         = sub;
     this.allReceived = allReceived;
     received         = 0;
     datas            = new List <string>();
 }
Пример #4
0
        private static void _subPullFetch(Context ctx, Stats stats, IJetStreamPullSubscription sub, int id, string counterKey)
        {
            int             rcvd         = 0;
            Msg             lastUnAcked  = null;
            int             unAckedCount = 0;
            int             unReported   = 0;
            string          label        = ctx.GetLabel(id);
            InterlockedLong counter      = ctx.GetSubscribeCounter(counterKey);

            while (counter.Read() < ctx.MessageCount)
            {
                stats.Start();
                IList <Msg> list     = sub.Fetch(ctx.BatchSize, 500);
                long        hold     = stats.Elapsed();
                long        received = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                int         lc       = list.Count;
                if (lc > 0)
                {
                    foreach (Msg m in list)
                    {
                        stats.Count(m, received);
                        counter.Increment();
                        if ((lastUnAcked = AckMaybe(ctx, stats, m, ++unAckedCount)) == null)
                        {
                            unAckedCount = 0;
                        }
                    }
                    rcvd      += lc;
                    unReported = ReportMaybe(label, ctx, rcvd, unReported + lc, "Messages Read");
                }
                AcceptHoldOnceStarted(label, stats, rcvd, hold);
            }
            if (lastUnAcked != null)
            {
                _ack(stats, lastUnAcked);
            }
            Report(label, rcvd, "Finished Reading Messages");
        }
Пример #5
0
        private static void SubPush(Context ctx, IConnection c, Stats stats, int id)
        {
            IJetStream js = c.CreateJetStreamContext(ctx.GetJetStreamOptions());
            IJetStreamPushSyncSubscription sub;

            if (ctx.Action.IsQueue)
            {
                // if we don't do this, multiple threads will try to make the same consumer because
                // when they start, the consumer does not exist. So force them do it one at a time.
                lock (QueueLock)
                {
                    sub = js.PushSubscribeSync(ctx.Subject, ctx.QueueName,
                                               ConsumerConfiguration.Builder()
                                               .WithAckPolicy(ctx.AckPolicy)
                                               .WithAckWait(Duration.OfSeconds(ctx.AckWaitSeconds))
                                               .WithDeliverGroup(ctx.QueueName)
                                               .BuildPushSubscribeOptions());
                }
            }
            else
            {
                sub = js.PushSubscribeSync(ctx.Subject,
                                           ConsumerConfiguration.Builder()
                                           .WithAckPolicy(ctx.AckPolicy)
                                           .WithAckWait(Duration.OfSeconds(ctx.AckWaitSeconds))
                                           .BuildPushSubscribeOptions());
            }

            int             rcvd         = 0;
            Msg             lastUnAcked  = null;
            int             unAckedCount = 0;
            int             unReported   = 0;
            string          label        = ctx.GetLabel(id);
            InterlockedLong counter      = ctx.GetSubscribeCounter(ctx.GetSubDurable(id));

            while (counter.Read() < ctx.MessageCount)
            {
                try
                {
                    stats.Start();
                    Msg  m        = sub.NextMessage(1000);
                    long hold     = stats.Elapsed();
                    long received = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                    stats.AcceptHold(hold);
                    stats.Count(m, received);
                    counter.Increment();
                    if ((lastUnAcked = AckMaybe(ctx, stats, m, ++unAckedCount)) == null)
                    {
                        unAckedCount = 0;
                    }
                    unReported = ReportMaybe(label, ctx, ++rcvd, ++unReported, "Messages Read");
                }
                catch (NATSTimeoutException)
                {
                    // normal timeout
                    long hold = stats.Elapsed();
                    AcceptHoldOnceStarted(label, stats, rcvd, hold);
                }
            }
            if (lastUnAcked != null)
            {
                _ack(stats, lastUnAcked);
            }
            Report(label, rcvd, "Finished Reading Messages");
        }