Exemplo n.º 1
0
        public async Task <PullResult> Pull(ChannelClient client, TmqMessage request)
        {
            QueueMessage message = _queue.FindNextMessage();

            if (message == null)
            {
                await client.Client.SendAsync(MessageBuilder.ResponseStatus(request, KnownContentTypes.NotFound));

                return(PullResult.Empty);
            }

            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 channel message
            message.Message.SetMessageId(request.MessageId);
            bool sent = client.Client.Send(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);
        }
Exemplo n.º 2
0
        public async Task <PullResult> Pull(ChannelClient client, TmqMessage request)
        {
            QueueMessage message = null;

            await _queue.RunInListSync(() =>
            {
                //pull from prefential messages
                if (_queue.HighPriorityLinkedList.Count > 0)
                {
                    message = _queue.HighPriorityLinkedList.First.Value;
                    _queue.HighPriorityLinkedList.RemoveFirst();

                    if (message != null)
                    {
                        message.IsInQueue = false;
                    }
                }

                //if there is no prefential message, pull from standard messages
                if (message == null && _queue.RegularLinkedList.Count > 0)
                {
                    message = _queue.RegularLinkedList.First.Value;
                    _queue.RegularLinkedList.RemoveFirst();

                    if (message != null)
                    {
                        message.IsInQueue = false;
                    }
                }
            });

            //there is no pullable message
            if (message == null)
            {
                await client.Client.SendAsync(MessageBuilder.ResponseStatus(request, KnownContentTypes.NotFound));

                return(PullResult.Empty);
            }

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

                    await _queue.ApplyDecision(decision, message);

                    if (decision.KeepMessage && !message.IsInQueue)
                    {
                        _queue.AddMessage(message, false);
                    }
                }
                catch //if developer does wrong operation, we should not stop
                {
                }
            }

            return(PullResult.Success);
        }
Exemplo n.º 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.RequestAcknowledge)
            {
                ackDeadline = DateTime.UtcNow.Add(_queue.Options.AcknowledgeTimeout);
            }

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

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

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

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

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

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

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

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

                //somehow if code comes here (it should not cuz of last "break" in this foreach, break
                if (!message.Message.FirstAcquirer && _queue.Options.SendOnlyFirstAcquirer)
                {
                    break;
                }

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

                final = ChannelQueue.CreateFinalDecision(final, ccrd);

                if (!ccrd.Allow)
                {
                    continue;
                }

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

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

                if (sent)
                {
                    messageIsSent = true;

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

                    //set as sent, if message is sent to it's first acquirer,
                    //set message first acquirer false and re-create byte array data of the message
                    bool firstAcquirer = message.Message.FirstAcquirer;

                    //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 = ChannelQueue.CreateFinalDecision(final, d);

                    //if we are sending to only first acquirer, break
                    if (_queue.Options.SendOnlyFirstAcquirer && firstAcquirer)
                    {
                        break;
                    }

                    if (firstAcquirer && clients.Count > 1)
                    {
                        messageData = await _writer.Create(message.Message);
                    }
                }
                else
                {
                    Decision d = await _queue.DeliveryHandler.ConsumerReceiveFailed(_queue, delivery, client.Client);

                    final = ChannelQueue.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.KeepMessage)
            {
                _queue.Info.AddMessageRemove();
                _ = _queue.DeliveryHandler.MessageRemoved(_queue, message);
            }

            return(PushResult.Success);
        }
Exemplo n.º 4
0
        private async Task <PushResult> ProcessMessage(QueueMessage message, ChannelClient receiver)
        {
            //if we need acknowledge from receiver, it has a deadline.
            DateTime?deadline = null;

            if (_queue.Options.RequestAcknowledge)
            {
                deadline = DateTime.UtcNow.Add(_queue.Options.AcknowledgeTimeout);
            }

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

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

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

            //create prepared message data
            byte[] messageData = await _writer.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);

            delivery.FirstAcquirer = message.Message.FirstAcquirer;

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

            if (sent)
            {
                //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.KeepMessage)
            {
                _queue.Info.AddMessageRemove();
                _ = _queue.DeliveryHandler.MessageRemoved(_queue, message);
            }

            return(PushResult.Success);
        }