Ejemplo n.º 1
0
        public void TestMultipleProducerCreateAndSend(
            [Values(MsgDeliveryMode.NonPersistent, MsgDeliveryMode.Persistent)]
            MsgDeliveryMode mode
            )
        {
            const int    MSG_TTL_MILLIS          = 8500; // 8.5 secs
            const int    NUM_MSGS                = 200;
            const int    NUM_PRODUCERS           = 5;
            const string MSG_ID_KEY              = "MsgIndex";
            const string PRODUCER_ID_KEY         = "ProducerIndex";
            const string PRODUCER_INDEXED_ID_KEY = "ProducerIndexedMsgId";
            bool         persistent              = mode.Equals(MsgDeliveryMode.Persistent);
            bool         useMsgId                = !persistent;
            int          msgIdWindow             = 0;

            string failureErr = null;

            IMessageProducer         producer  = null;
            IList <IMessageProducer> producers = null;
            IList <int> lastProducerIndexedIds = null;

            try
            {
                using (IConnection connection = this.GetConnection("c1"))
                    using (ISession session = this.GetSession("s1"))
                        using (IDestination destination = this.GetDestination("t1"))
                            using (IMessageConsumer drain = this.GetConsumer("drain"))
                            {
                                lastProducerIndexedIds = new List <int>();
                                MessageListener ackCallback = CreateListener(NUM_MSGS);

                                drain.Listener += (message) =>
                                {
                                    if (failureErr == null)
                                    {
                                        ackCallback(message);
                                        int id           = message.Properties.GetInt(PRODUCER_INDEXED_ID_KEY);
                                        int prodIndex    = message.Properties.GetInt(PRODUCER_ID_KEY);
                                        int lastId       = lastProducerIndexedIds[prodIndex];
                                        int advancedMsgs = id - lastId;
                                        if (id < lastId)
                                        {
                                            failureErr = string.Format(
                                                "Received message out of order." +
                                                " Received, sent from producer {0} msg id {1} where last msg id {2}",
                                                prodIndex,
                                                id,
                                                lastId
                                                );
                                            this.waiter.Set();
                                        }
                                        else if (persistent && advancedMsgs > 1)
                                        {
                                            failureErr = string.Format(
                                                "Persistent Messages where drop." +
                                                " Received, sent from producer {0} msg id {1} where last msg id {2}",
                                                prodIndex,
                                                id,
                                                lastId
                                                );
                                            this.waiter.Set();
                                        }
                                        else
                                        {
                                            lastProducerIndexedIds[prodIndex] = id;
                                            if (advancedMsgs > 1 && (Logger.IsInfoEnabled || Logger.IsDebugEnabled))
                                            {
                                                Logger.Info(string.Format(
                                                                "{0} Messages dropped for producer {1} from message id {2}",
                                                                advancedMsgs, prodIndex, lastId
                                                                ));
                                            }
                                            msgIdWindow += advancedMsgs;
                                            if (!persistent && msgIdWindow == NUM_MSGS)
                                            {
                                                this.waiter.Set();
                                            }
                                        }
                                    }
                                };

                                connection.ExceptionListener += DefaultExceptionListener;

                                producers = new List <IMessageProducer>();
                                for (int i = 0; i < NUM_PRODUCERS; i++)
                                {
                                    try
                                    {
                                        producer = session.CreateProducer(destination);
                                    }
                                    catch (Exception ex)
                                    {
                                        this.PrintTestFailureAndAssert(this.GetMethodName(), "Failed to Created Producer " + i, ex);
                                    }
                                    producer.DeliveryMode     = mode;
                                    producer.DisableMessageID = !useMsgId;
                                    producer.TimeToLive       = TimeSpan.FromMilliseconds(MSG_TTL_MILLIS);
                                    producers.Add(producer);
                                    lastProducerIndexedIds.Add(-1);
                                }

                                connection.Start();

                                Assert.AreEqual(NUM_PRODUCERS, producers.Count, "Did not create all producers.");
                                Assert.IsNull(asyncEx,
                                              "Exception Listener Called While creating producers. With exception {0}.",
                                              asyncEx);

                                ITextMessage msg           = session.CreateTextMessage();
                                int          producerIndex = -1;
                                for (int i = 0; i < NUM_MSGS; i++)
                                {
                                    msg.Text = "Index:" + i;
                                    msg.Properties[MSG_ID_KEY] = i;
                                    msg.Properties[PRODUCER_INDEXED_ID_KEY] = i / NUM_PRODUCERS;
                                    producerIndex = i % NUM_PRODUCERS;
                                    msg.Properties[PRODUCER_ID_KEY] = producerIndex;
                                    producers[producerIndex].Send(msg);
                                }

                                Assert.IsNull(asyncEx, "Exception Listener Called While sending messages. With exception {0}.", asyncEx);

                                Assert.IsTrue(waiter.WaitOne(TIMEOUT),
                                              "Failed to received all messages in {0}ms. Received {1} of {2} messages",
                                              TIMEOUT, msgCount, NUM_MSGS);

                                Assert.IsNull(failureErr,
                                              "Received assertion failure from IMessageConsumer message Listener. Failure : {0}",
                                              failureErr ?? "");

                                if (persistent)
                                {
                                    Assert.AreEqual(NUM_MSGS, msgCount,
                                                    "Receive unexpected from messages sent. Message Window {0}", msgIdWindow);
                                }
                                else
                                {
                                    int missedMsgs = (msgIdWindow - msgCount);
                                    Assert.AreEqual(NUM_MSGS, msgIdWindow,
                                                    "Failed to receive all messages." +
                                                    " Received {0} of {1} messages, with missed messages {2}, in {3}ms",
                                                    msgCount, NUM_MSGS, missedMsgs, TIMEOUT
                                                    );
                                    if (missedMsgs > 0)
                                    {
                                        System.Text.StringBuilder sb = new System.Text.StringBuilder();
                                        const string SEPARATOR       = ", ";
                                        for (int i = 0; i < NUM_PRODUCERS; i++)
                                        {
                                            sb.AppendFormat("Last received Producer {0} message id  {1}{2}", i, lastProducerIndexedIds[i], SEPARATOR);
                                        }
                                        sb.Length = sb.Length - SEPARATOR.Length;

                                        Logger.Warn(string.Format("Did not receive all Non Persistent messages. Received {0} of {1} messages. Where last received message ids = [{2}]", msgCount, NUM_MSGS, sb.ToString()));
                                    }
                                }

                                Assert.IsNull(asyncEx, "Exception Listener Called While receiveing messages. With exception {0}.", asyncEx);
                                //
                                // Some brokers are sticklers for detail and actually honor the
                                // batchable flag that AMQPnetLite sets on all published messages. As
                                // a result all messages can be long received before the published
                                // messages are acknowledged. So to avoid a hand full of
                                // amqp:message:released outcomes, just pause a few seconds before
                                // closing the producer
                                System.Threading.Thread.Sleep(3000);
                            }
            }
            catch (Exception e)
            {
                this.PrintTestFailureAndAssert(this.GetMethodName(), "Unexpected Exception.", e);
            }
            finally
            {
                if (producers != null)
                {
                    foreach (IMessageProducer p in producers)
                    {
                        p?.Close();
                        p?.Dispose();
                    }
                    producers.Clear();
                }
            }
        }
        [ProducerSetup("default", "testdest4", "pro4")]//*/
        public void TestMultipleConsumerMessageListenerReceive()
        {
            const int NUM_MSGS = 100000;

            string[] conIds = new string[] { "con1", "con2", "con3", "con4" };
            string[] proIds = new string[] { "pro1", "pro2", "pro3", "pro4" };
            IList <IMessageConsumer> consumers = this.GetConsumers(conIds);
            IList <IMessageProducer> producers = this.GetProducers(proIds);
            int ProducerCount = producers.Count;
            int ConsumerCount = consumers.Count;

            long[]          lastMsgId           = new long[ConsumerCount];
            long[]          MissingMsgCount     = new long[ConsumerCount];
            long            lostMsgCount        = 0;
            int             TotalMsgs           = NUM_MSGS * ProducerCount;
            long            undeliveredMsgCount = TotalMsgs;
            int             timeout             = Math.Max(TotalMsgs / 1000, 1) * 1100;
            MsgDeliveryMode mode = MsgDeliveryMode.NonPersistent;

            using (IConnection connection = this.GetConnection("default"))
            {
                connection.ExceptionListener += DefaultExceptionListener;

                for (int i = 0; i < ConsumerCount; i++)
                {
                    lastMsgId[i]       = -1;
                    MissingMsgCount[i] = 0;
                }
                try
                {
                    MessageListener callback = CreateListener(TotalMsgs);
                    int             index    = 0;
                    foreach (IMessageConsumer consumer in consumers)
                    {
                        int             num = index;
                        MessageListener countingCallback = (m) =>
                        {
                            long lastId = lastMsgId[num];
                            long msgId  = ExtractMsgId(m.NMSMessageId);
                            if (msgId > lastId)
                            {
                                lastMsgId[num] = msgId;
                                if (lastId != -1)
                                {
                                    MissingMsgCount[num] += (msgId - (lastId + 1));
                                    lostMsgCount         += (msgId - (lastId + 1));
                                }
                            }
                            callback(m);

                            // signal envent waiter when the last expected msg is delivered on all consumers
                            if (lostMsgCount + msgCount == TotalMsgs)
                            {
                                // signal if detected lost msgs from id gap and delivered msgs make the total msgs.
                                waiter?.Set();
                            }
                            else if (lastMsgId[num] == NUM_MSGS - 1)
                            {
                                // signal if final msg id on every consumer is detected.
                                undeliveredMsgCount -= NUM_MSGS;
                                if (undeliveredMsgCount <= 0)
                                {
                                    waiter?.Set();
                                }
                            }
                        };

                        consumer.Listener += countingCallback;
                        index++;
                    }

                    connection.Start();

                    // send messages to Destinations
                    ITextMessage sendMsg = producers[0].CreateTextMessage();
                    for (int i = 0; i < NUM_MSGS; i++)
                    {
                        int link = 0;
                        foreach (IMessageProducer producer in producers)
                        {
                            sendMsg.Text = "Link: " + link + ", num:" + i;
                            link++;
                            producer.Send(sendMsg, mode, MsgPriority.Normal, TimeSpan.Zero);
                        }
                    }

                    if (!waiter.WaitOne(timeout))
                    {
                        if (mode.Equals(MsgDeliveryMode.NonPersistent))
                        {
                            if (msgCount != TotalMsgs)
                            {
                                Logger.Warn(string.Format("Only received {0} of {1} messages in {2}ms.", msgCount, TotalMsgs, timeout));

                                LogSummary(MissingMsgCount, lastMsgId, NUM_MSGS);
                            }

                            Assert.IsNull(asyncEx, "Received unexpected asynchronous exception. Message : {0}", asyncEx?.Message);
                        }
                        else
                        {
                            Assert.Fail("Only received {0} of {1} messages in {2}ms.", msgCount, TotalMsgs, timeout);
                        }
                    }
                    else
                    {
                        if (msgCount != TotalMsgs)
                        {
                            Logger.Warn(string.Format("Only received {0} of {1} messages in {2}ms.", msgCount, TotalMsgs, timeout));

                            LogSummary(MissingMsgCount, lastMsgId, NUM_MSGS);
                        }

                        Assert.IsNull(asyncEx, "Received unexpected asynchronous exception. Message : {0}", asyncEx?.Message);

                        long ActualMsgs = mode.Equals(MsgDeliveryMode.NonPersistent) ? msgCount + lostMsgCount : msgCount;

                        Assert.AreEqual(TotalMsgs, ActualMsgs, "Only received {0} (delivered = {1}, lost = {2}) of {3} messages in {4}ms.", ActualMsgs, msgCount, lostMsgCount, TotalMsgs, timeout);
                    }
                }
                catch (Exception ex)
                {
                    this.PrintTestFailureAndAssert(GetTestMethodName(), "Unexpected Exception.", ex);
                }
                finally
                {
                    // sleep for 2 seconds to allow for pending procuder acknowledgements to be received from the broker.
                    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
                }
            }
        }
Ejemplo n.º 3
0
        protected void DoSend(IDestination destination, IMessage message, MsgDeliveryMode deliveryMode, MsgPriority priority, TimeSpan timeToLive)
        {
            this.Attach();
            bool sendSync = deliveryMode.Equals(MsgDeliveryMode.Persistent);

            if (destination.IsTemporary && (destination as TemporaryDestination).IsDeleted)
            {
                throw new InvalidDestinationException("Can not send message on deleted temporary topic.");
            }
            message.NMSDestination  = destination;
            message.NMSDeliveryMode = deliveryMode;
            message.NMSPriority     = priority;
            // If there is  timeToLive, set it before setting NMSTimestamp as timeToLive
            // is required to calculate absolute expiry time.
            // TBD: If the messageProducer has a non-default timeToLive and the message
            // already has a timeToLive set by application, which should take precedence, this
            // code overwrites the message TimeToLive in this case but not if the producer TimeToLive
            // is the default ...
            if (timeToLive != NMSConstants.defaultTimeToLive)
            {
                message.NMSTimeToLive = timeToLive;
            }
            if (!DisableMessageTimestamp)
            {
                message.NMSTimestamp = DateTime.UtcNow;
            }


            if (!DisableMessageID)
            {
                message.NMSMessageId = MessageIdGenerator.GenerateId().ToString();
            }

            Amqp.Message amqpmsg = null;
            if (message is Message.Message)
            {
                Message.Message copy = (message as Message.Message).Copy();
                copy.NMSDestination = DestinationTransformation.Transform(Session.Connection, destination);
                PrepareMessageForSend(copy);
                IMessageCloak cloak = copy.GetMessageCloak();
                if (cloak is AMQPMessageCloak)
                {
                    amqpmsg = (cloak as AMQPMessageCloak).AMQPMessage;
                }
            }
            else
            {
                Message.Message nmsmsg = this.Session.Connection.TransformFactory.TransformMessage <Message.Message>(message);
                PrepareMessageForSend(nmsmsg);
                IMessageCloak cloak = nmsmsg.GetMessageCloak().Copy();
                if (cloak is AMQPMessageCloak)
                {
                    amqpmsg = (cloak as AMQPMessageCloak).AMQPMessage;
                }
            }



            if (amqpmsg != null)
            {
                if (Tracer.IsDebugEnabled)
                {
                    Tracer.DebugFormat("Sending message : {0}", message.ToString());
                }

                if (sendSync)
                {
                    DoAMQPSendSync(amqpmsg, this.RequestTimeout);
                }
                else
                {
                    DoAMQPSendAsync(amqpmsg, HandleAsyncAMQPMessageOutcome);
                }
            }
        }