Example #1
0
        private async Task <bool> SendRoundRobin(HorseMessage message)
        {
            Interlocked.Increment(ref _roundRobinIndex);
            int i = _roundRobinIndex;

            if (i >= _queues.Length)
            {
                _roundRobinIndex = 0;
                i = 0;
            }

            if (_queues.Length == 0)
            {
                return(false);
            }

            HorseQueue queue = Router.Server.FindQueue(message.Target);

            if (queue == null)
            {
                if (!Router.Server.Options.AutoQueueCreation)
                {
                    return(false);
                }

                queue = await Router.Server.CreateQueue(message.Target, Router.Server.Options, message, Router.Server.DeliveryHandlerFactory, true, true);
            }

            QueueMessage queueMessage = new QueueMessage(message);

            queue.AddMessage(queueMessage);
            return(true);
        }
        public async Task <PushResult> Push(QueueMessage message)
        {
            try
            {
                QueueClient cc;
                if (_queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge)
                {
                    Tuple <QueueClient, int> tuple = await _queue.GetNextAvailableRRClient(_roundRobinIndex);

                    cc = tuple.Item1;
                    if (cc != null)
                    {
                        _roundRobinIndex = tuple.Item2;
                    }
                }
                else
                {
                    cc = _queue.GetNextRRClient(ref _roundRobinIndex);
                }

                /*
                 * //if to process next message is requires previous message acknowledge, wait here
                 * if (_queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge)
                 *  await _queue.WaitForAcknowledge(message);
                 */

                if (cc == null)
                {
                    _queue.AddMessage(message, false);
                    return(PushResult.NoConsumers);
                }

                ProcessingMessage = message;
                PushResult result = await ProcessMessage(message, cc);

                ProcessingMessage = null;

                return(result);
            }
            catch (Exception e)
            {
                _queue.Server.SendError("PUSH", e, $"QueueName:{_queue.Name}, State:RoundRobin");
                return(PushResult.Error);
            }
        }
Example #3
0
        private async Task <bool> SendOnlyFirst(HorseMessage message)
        {
            if (_queues.Length < 1)
            {
                return(false);
            }

            HorseQueue queue = Router.Server.FindQueue(message.Target);

            if (queue == null)
            {
                if (!Router.Server.Options.AutoQueueCreation)
                {
                    return(false);
                }

                queue = await Router.Server.CreateQueue(message.Target, Router.Server.Options, message, Router.Server.DeliveryHandlerFactory, true, true);
            }

            QueueMessage queueMessage = new QueueMessage(message);

            queue.AddMessage(queueMessage);
            return(true);
        }
Example #4
0
        public async Task <PullResult> Pull(QueueClient client, HorseMessage request)
        {
            int index = 1;
            int count = FindCount(request);

            if (count < 1)
            {
                await client.Client.SendAsync(MessageBuilder.CreateNoContentPullResponse(request, HorseHeaders.UNACCEPTABLE));

                return(PullResult.Unacceptable);
            }

            ClearDecision clear    = FindClearDecision(request);
            bool          sendInfo = FindInfoRequest(request);
            bool          fifo     = FindOrder(request);

            Tuple <QueueMessage, int, int> messageTuple = await DequeueMessage(fifo, sendInfo, count == index?clear : ClearDecision.None);

            //there is no pullable message
            if (messageTuple.Item1 == null)
            {
                await client.Client.SendAsync(MessageBuilder.CreateNoContentPullResponse(request, HorseHeaders.EMPTY));

                return(PullResult.Empty);
            }

            List <KeyValuePair <string, string> > headers     = new List <KeyValuePair <string, string> >();
            KeyValuePair <string, string>         requestId   = new KeyValuePair <string, string>(HorseHeaders.REQUEST_ID, request.MessageId);
            KeyValuePair <string, string>         countHeader = new KeyValuePair <string, string>(HorseHeaders.COUNT, count.ToString());

            while (index <= count)
            {
                QueueMessage message = messageTuple.Item1;
                if (message == null)
                {
                    break;
                }

                try
                {
                    headers.Add(requestId);
                    headers.Add(countHeader);
                    headers.Add(new KeyValuePair <string, string>(HorseHeaders.INDEX, index.ToString()));

                    if (sendInfo)
                    {
                        headers.Add(new KeyValuePair <string, string>(HorseHeaders.PRIORITY_MESSAGES, messageTuple.Item2.ToString()));
                        headers.Add(new KeyValuePair <string, string>(HorseHeaders.MESSAGES, messageTuple.Item3.ToString()));
                    }

                    bool processed = await ProcessPull(client, request, message, headers);

                    if (!processed)
                    {
                        break;
                    }

                    index++;
                    messageTuple = await DequeueMessage(fifo, sendInfo, count == index?clear : ClearDecision.None);

                    headers.Clear();
                }
                catch (Exception ex)
                {
                    _queue.Info.AddError();
                    try
                    {
                        Decision decision = await _queue.DeliveryHandler.ExceptionThrown(_queue, message, ex);

                        await _queue.ApplyDecision(decision, message);

                        if (!message.IsInQueue)
                        {
                            if (decision.PutBack == PutBackDecision.Start)
                            {
                                _queue.AddMessage(message, false);
                            }
                            else if (decision.PutBack == PutBackDecision.End)
                            {
                                _queue.AddMessage(message);
                            }
                        }
                    }
                    catch //if developer does wrong operation, we should not stop
                    {
                    }
                }
            }

            await client.Client.SendAsync(MessageBuilder.CreateNoContentPullResponse(request, HorseHeaders.END));

            return(PullResult.Success);
        }
Example #5
0
        private async Task <PushResult> ProcessMessage(QueueMessage message)
        {
            //if we need acknowledge from receiver, it has a deadline.
            DateTime?ackDeadline = null;

            if (_queue.Options.Acknowledge != QueueAckDecision.None)
            {
                ackDeadline = DateTime.UtcNow.Add(_queue.Options.AcknowledgeTimeout);
            }

            //if to process next message is requires previous message acknowledge, wait here
            if (_queue.Options.Acknowledge == QueueAckDecision.WaitForAcknowledge)
            {
                await _queue.WaitForAcknowledge(message);
            }

            //if there are not receivers, complete send operation
            List <QueueClient> clients = _queue.ClientsClone;

            if (clients.Count == 0)
            {
                _queue.AddMessage(message, false);
                return(PushResult.NoConsumers);
            }

            if (message.CurrentDeliveryReceivers.Count > 0)
            {
                message.CurrentDeliveryReceivers.Clear();
            }

            message.Decision = await _queue.DeliveryHandler.BeginSend(_queue, message);

            if (!await _queue.ApplyDecision(message.Decision, message))
            {
                return(PushResult.Success);
            }

            //create prepared message data
            byte[] messageData = HmqWriter.Create(message.Message);

            Decision final         = new Decision(false, false, PutBackDecision.No, DeliveryAcknowledgeDecision.None);
            bool     messageIsSent = false;

            //to all receivers
            foreach (QueueClient client in clients)
            {
                //to only online receivers
                if (!client.Client.IsConnected)
                {
                    continue;
                }

                //call before send and check decision
                Decision ccrd = await _queue.DeliveryHandler.CanConsumerReceive(_queue, message, client.Client);

                final = HorseQueue.CreateFinalDecision(final, ccrd);

                if (!ccrd.Allow)
                {
                    continue;
                }

                //create delivery object
                MessageDelivery delivery = new MessageDelivery(message, client, ackDeadline);

                //send the message
                bool sent = await client.Client.SendAsync(messageData);

                if (sent)
                {
                    if (_queue.Options.Acknowledge != QueueAckDecision.None)
                    {
                        client.CurrentlyProcessing = message;
                        client.ProcessDeadline     = ackDeadline ?? DateTime.UtcNow;
                    }

                    messageIsSent = true;
                    message.CurrentDeliveryReceivers.Add(client);

                    //adds the delivery to time keeper to check timing up
                    _queue.TimeKeeper.AddAcknowledgeCheck(delivery);

                    //mark message is sent
                    delivery.MarkAsSent();

                    //do after send operations for per message
                    _queue.Info.AddDelivery();
                    Decision d = await _queue.DeliveryHandler.ConsumerReceived(_queue, delivery, client.Client);

                    final = HorseQueue.CreateFinalDecision(final, d);
                }
                else
                {
                    Decision d = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, client.Client);

                    final = HorseQueue.CreateFinalDecision(final, d);
                }
            }

            message.Decision = final;
            if (!await _queue.ApplyDecision(final, message))
            {
                return(PushResult.Success);
            }

            //after all sending operations completed, calls implementation send completed method and complete the operation
            if (messageIsSent)
            {
                _queue.Info.AddMessageSend();
            }

            message.Decision = await _queue.DeliveryHandler.EndSend(_queue, message);

            await _queue.ApplyDecision(message.Decision, message);

            if (message.Decision.Allow && message.Decision.PutBack == PutBackDecision.No)
            {
                _queue.Info.AddMessageRemove();
                _ = _queue.DeliveryHandler.MessageDequeued(_queue, message);
            }

            return(PushResult.Success);
        }