private async Task <PushResult> ProcessMessage(QueueMessage message, QueueClient receiver)
        {
            //if we need acknowledge from receiver, it has a deadline.
            DateTime?deadline = null;

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

            //return if client unsubsribes while waiting ack of previous message
            if (!_queue.ClientsClone.Contains(receiver))
            {
                _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);

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

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

            //create delivery object
            MessageDelivery delivery = new MessageDelivery(message, receiver, deadline);

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

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

                message.CurrentDeliveryReceivers.Add(receiver);

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

                //mark message is sent
                delivery.MarkAsSent();
                _queue.Info.AddMessageSend();

                //do after send operations for per message
                _queue.Info.AddDelivery();
                message.Decision = await _queue.DeliveryHandler.ConsumerReceived(_queue, delivery, receiver.Client);
            }
            else
            {
                message.Decision = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, receiver.Client);
            }

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

            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);
        }
示例#2
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);
        }
示例#3
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);
        }
示例#4
0
        public async Task <PullResult> Pull(QueueClient client, HorseMessage request)
        {
            QueueMessage message = _queue.FindNextMessage();

            if (message == null)
            {
                await client.Client.SendAsync(request.CreateResponse(HorseResultCode.NotFound));

                return(PullResult.Empty);
            }

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

            ProcessingMessage = message;

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

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

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

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

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

            //change to response message, send, change back to queue message
            message.Message.SetMessageId(request.MessageId);
            bool sent = await client.Client.SendAsync(message.Message);

            if (sent)
            {
                delivery.MarkAsSent();

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

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

                if (!await _queue.ApplyDecision(message.Decision, message))
                {
                    return(PullResult.Success);
                }
            }
            else
            {
                message.Decision = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, client.Client);

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

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

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

            return(PullResult.Success);
        }
        private async Task <PushResult> ProcessMessage(QueueMessage message)
        {
            //if there are not receivers, complete send operation
            List <QueueClient> clients = _queue.ClientsClone;

            if (clients.Count == 0)
            {
                _queue.Info.AddMessageRemove();
                return(PushResult.NoConsumers);
            }

            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);

            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);

                if (!ccrd.Allow)
                {
                    continue;
                }

                //send the message
                _ = client.Client.SendAsync(messageData);

                messageIsSent = true;

                //do after send operations for per message
                _queue.Info.AddDelivery();
            }

            //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();
            }

            return(PushResult.Success);
        }