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