/// <summary>
        /// Creates a RpcClient for each configured queue defined by other applications
        /// servers to which messages can be published and a response is expected. The
        /// external RPC queues exposed by other applications are specified within the
        /// configuration file.
        /// </summary>
        /// <param name="brokerName">The optional broker name to create RPC client for.</param>
        public void DeclareRpcClients(string brokerName = null)
        {
            IEnumerable <BrokerConnectionSettings> brokerConnections = _brokerState.BrokerSettings.Connections;

            // The broker name will be null when all the RPC response queues need to be re-created after
            // a connection exception is detected.
            if (brokerName != null)
            {
                brokerConnections = brokerConnections.Where(c => c.BrokerName == brokerName);
            }

            foreach (BrokerConnectionSettings brokerConn in brokerConnections)
            {
                foreach (RpcConsumerSettings rpcConsumer in brokerConn.RpcConsumers)
                {
                    // The channel to await for replays to published messages.
                    IModel replyChannel = _connMgr.CreateChannel(brokerConn.BrokerName);

                    var rpcClient    = new RpcClient(brokerConn.BrokerName, rpcConsumer, replyChannel);
                    var rpcPublisher = new RpcMessagePublisher(brokerConn.BrokerName, rpcConsumer, rpcClient);

                    _rpcMessagePublishers.Add(rpcPublisher);
                }
            }
        }
 private void LogReceivedRpcResponse(IMessage message,
                                     RpcMessagePublisher rpcPublisher)
 {
     _logger.LogTraceDetails(RabbitMqLogEvents.PUBLISHER_RPC_RESPONSE, "RPC Reply Message Received",
                             new
     {
         Message = message,
         rpcPublisher.BrokerName,
         rpcPublisher.RequestQueueName,
         rpcPublisher.Client.ReplyQueueName
     });
 }
        private RpcMessagePublisher GetRpcPublisher(RpcCommandAttribute consumerAttrib)
        {
            RpcMessagePublisher rpcPublisher = _rpcMessagePublishers.FirstOrDefault(c =>
                                                                                    c.BrokerName == consumerAttrib.BrokerName &&
                                                                                    c.RequestQueueKey == consumerAttrib.RequestQueueKey);

            if (rpcPublisher == null)
            {
                throw new BrokerException(
                          $"RPC Publisher Client could not configured for Broker: {consumerAttrib.BrokerName} " +
                          $"RequestQuoteKey: {consumerAttrib.RequestQueueKey}.");
            }
            return(rpcPublisher);
        }
 private void LogPublishedRpcMessage(IMessage message,
                                     RpcMessagePublisher rpcPublisher,
                                     RpcProperties rpcProps)
 {
     _logger.LogTraceDetails(RabbitMqLogEvents.PUBLISHER_RPC_REQUEST, "Publishing to RPC Consumer",
                             new
     {
         Message = message,
         rpcPublisher.BrokerName,
         rpcPublisher.RequestQueueKey,
         rpcPublisher.RequestQueueName,
         rpcPublisher.Client.ReplyQueueName,
         rpcProps.ContentType,
         rpcProps.ExternalTypeName
     });
 }
        /// <summary>
        /// Publishes a message to a consumer defined queue used for receiving
        /// RPC style messages.  The caller awaits the reply response message.
        /// </summary>
        /// <param name="message">The RPC style message to publish.</param>
        /// <returns>Future result after the reply is received.</returns>
        public async Task PublishToRpcConsumerAsync(IMessage message, CancellationToken cancellationToken)
        {
            Check.NotNull(message, nameof(message));

            AssertRpcCommand(message);

            var rpcCommandAttrib = message.GetAttribute <RpcCommandAttribute>();
            var command          = message as ICommand;

            RpcProperties rpcProps = new RpcProperties {
                ContentType      = rpcCommandAttrib.ContentType,
                ExternalTypeName = rpcCommandAttrib.ExternalTypeName
            };

            // Obtain the consumer queue on which the message should be published.
            RpcMessagePublisher rpcPublisher = GetRpcPublisher(rpcCommandAttrib);

            string[] orderedContentTypes =
            {
                message.GetContentType(),
                rpcProps.ContentType,
                rpcPublisher.ContentType
            };

            byte[] messageBody = _serializationMgr.Serialize(command, orderedContentTypes);

            LogPublishedRpcMessage(message, rpcPublisher, rpcProps);

            // Publish the RPC request the consumer's queue and await a response.
            rpcProps.ContentType = command.GetContentType();
            byte[] replyBody = null;

            try
            {
                replyBody = await rpcPublisher.Client.Invoke(command, rpcProps, cancellationToken, messageBody);

                object reply = _serializationMgr.Deserialize(rpcProps.ContentType, command.ResultType, replyBody);
                command.SetResult(reply);
                LogReceivedRpcResponse(message, rpcPublisher);
            }
            catch (RpcReplyException ex)
            {
                var dispatchEx = _serializationMgr.Deserialize <MessageDispatchException>(rpcProps.ContentType, ex.Exception);
                _logger.LogError(RabbitMqLogEvents.PUBLISHER_RPC_RESPONSE, "RPC Exception Reply.", dispatchEx);
                throw dispatchEx;
            }
        }