Exemplo n.º 1
0
        public async Task <bool> ReplyAsync <T>(T message, IDictionary <string, object> headers = null)
        {
            await Task.Delay(0, LocalCancellationToken);

            if (EndpointType != EndpointTypeEnum.RpcConsumer)
            {
                var e = new InvalidOperationException("Attempt to reply to a message on a non Rpc Consumer prohibited.");
                VerboseLoggingHandler.Log(e);
                throw e;
            }

            var bMessage = EnsureByteArrayFromGeneric(message);

            if (bMessage == null)
            {
                return(false);
            }

            VerboseLoggingHandler.Log($"Replying to message");
            var args = new Dictionary <string, object>();

            if (_rpcResponseChannel == null)
            {
                VerboseLoggingHandler.Log($"Response queue not open yet. Creating one now");
                if (QueueTtlValues.ContainsKey(ReplyToQueueName))
                {
                    args.Add(DictionaryKey_QueueTtl, QueueTtlValues[ReplyToQueueName]);
                }
                VerboseLoggingHandler.Log($"Using requested ttl='{QueueTtlValues[ReplyToQueueName]}'");
                _rpcResponseChannel = _RabbitOut.CreateModel();
                // Use the same TTL value as was used to create the queue on the other side
                _rpcResponseChannel.QueueDeclare(ReplyToQueueName, false, false, true, args);
                VerboseLoggingHandler.Log($"Queue ready");
            }

            var messageProperties = _rpcResponseChannel.CreateBasicProperties();
            var rp = ReplyPriority;

            if (rp > 0)
            {
                rp--;
            }
            messageProperties.Priority   = rp;
            messageProperties.Headers    = headers;
            messageProperties.Type       = MessageTypeFragmentsReply;
            messageProperties.Persistent = false;
            VerboseLoggingHandler.Log($"Publishing reply");
            _rpcResponseChannel.BasicPublish("", ReplyToQueueName, true, messageProperties, bMessage);
            VerboseLoggingHandler.Log($"Sent");
            return(true);
        }
Exemplo n.º 2
0
        protected virtual async Task OnIncomingMessageAsync(object sender, BasicDeliverEventArgs ea)
        {
            await Task.Delay(0, LocalCancellationToken);

            var ackMode     = ((ConsumerParameters)ChannelParameters).AutoAckMode;
            var isRpc       = false;
            var requiresAck = false;

            VerboseLoggingHandler.Log($"Event OnIncomingMessageAsync triggered For tag='{ea.DeliveryTag}', exchange='{ea.Exchange}', routingKeyOrTopicName='{ea.RoutingKey}', consumerTag='{ea.ConsumerTag}', deliveryTag='{ea.DeliveryTag}', redelivered='{ea.Redelivered}'");

            var messageType = ea.BasicProperties.Type;

            if (!ea.BasicProperties.IsCorrelationIdPresent())
            {
                var e = new InvalidOperationException($"Missing correlationId in message from exchange={ea.Exchange} deliveryTag=${ea.DeliveryTag}");
                VerboseLoggingHandler.Log(e);
                throw e;
            }

            VerboseLoggingHandler.Log($"MessageType='{messageType}'");

            if (messageType.Contains(MessageTypeFragmentsRequestAmqAck))
            {
                if (ackMode == ConsumerParameters.AutoAckModeEnum.OnReceipt)
                {
                    Channel.BasicAck(ea.DeliveryTag, false);
                }
                if (ackMode == ConsumerParameters.AutoAckModeEnum.Manual)
                {
                    requiresAck = true;
                }
            }

            if ((messageType.Contains(MessageTypeFragmentsRequestAck) || messageType.Contains(MessageTypeFragmentsRequestReply) && ea.BasicProperties.IsReplyToPresent()))
            {
                isRpc            = true;
                EndpointType     = EndpointTypeEnum.RpcConsumer;
                ReplyToQueueName = ea.BasicProperties.ReplyTo;
                VerboseLoggingHandler.Log($"Reply requested to '{ReplyToQueueName}'");

                if (ea.BasicProperties.IsHeadersPresent())
                {
                    VerboseLoggingHandler.Log($"Headers found");

                    var headers = ea.BasicProperties.Headers;
                    if (headers.ContainsKey(DictionaryKey_PassedQueueTtl))
                    {
                        var ttl = Convert.ToInt32(headers[DictionaryKey_PassedQueueTtl]);
                        VerboseLoggingHandler.Log($"ttl='{ttl}'");

                        if (QueueTtlValues.ContainsKey(ReplyToQueueName))
                        {
                            QueueTtlValues[ReplyToQueueName] = ttl;
                        }
                        else
                        {
                            QueueTtlValues.Add(ReplyToQueueName, ttl);
                        }

                        ea.BasicProperties.Headers.Remove(DictionaryKey_PassedQueueTtl);
                    }
                }

                // Handle basic message acknowledgement here.
                if (messageType.Contains(MessageTypeFragmentsRequestAck) && ConvertMessageToString(ea.Body) == MessageContent_Ping)
                {
                    VerboseLoggingHandler.Log($"Ack'ing the Ping");
                    await ReplyAsync(MessageContent_PingResponse, null);
                }
            }

            VerboseLoggingHandler.Log($"Delegate check - does messageType have '{MessageTypeFragmentsRequestReply}'?");
            if (messageType.Contains(MessageTypeFragmentsRequestReply))
            {
                VerboseLoggingHandler.Log($"Confirmed. Fire delegate");
                var args = new IncomingRabbitMqMessageEventArgs(isRpc, requiresAck, ea);
                await Task.Run(() => IncomingMessage?.Invoke(this, args), LocalCancellationToken);
            }
        }