private static void LogReceivedRpcResponse(IPublisherContext context, CreatedExchange createdExchange, object responseObj)
        {
            var definition = createdExchange.Definition;

            context.Logger.LogTraceDetails(
                $"Response to RPC message sent to queue: {definition.QueueMeta.QueueName} on bus: {definition.BusName}", responseObj);
        }
示例#2
0
 // Add properties used by the receiving consumer required for sending
 // the response to the reply queue.
 private void AppendRpcMessageProperties(MessageProperties msgProps, CreatedExchange createdExchange)
 {
     msgProps.ReplyTo       = ReplyToQueueName;
     msgProps.CorrelationId = msgProps.CorrelationId ?? Guid.NewGuid().ToString();
     msgProps.SetRpcReplyBusConfigName(_busName);
     msgProps.SetRpcActionNamespace(createdExchange.Definition.ActionNamespace);
 }
        public async Task Publish(IPublisherContext context, CreatedExchange createdExchange,
                                  IMessage message,
                                  CancellationToken cancellationToken)
        {
            // Prepare the message and its defining properties to be published.
            byte[]            messageBody       = context.Serialization.Serialize(message, createdExchange.Definition.ContentType);
            MessageProperties messageProperties = GetMessageProperties(context, createdExchange, message);
            string            routeKey          = message.GetRouteKey() ?? createdExchange.Definition.RouteKey;

            // Only send the message to the exchange if satisfying all constraints configured for the exchange.
            // This only applies to domain-events, as commands are more specific in that they are explicitly
            // requesting a behavior to be taken.
            if (message is IDomainEvent &&
                !await Satisfies(context, createdExchange, message).ConfigureAwait(false))
            {
                return;
            }

            // Delegate to EasyNetQ to publish the message.
            await createdExchange.Bus.Advanced.PublishAsync(createdExchange.Exchange,
                                                            routeKey ?? string.Empty,
                                                            false,
                                                            messageProperties,
                                                            messageBody).ConfigureAwait(false);
        }
示例#4
0
        private void LogRpcPublishDetails(CreatedExchange createdExchange, string correlationId)
        {
            string receiverQueue = createdExchange.Definition.QueueMeta.QueueName;
            string actionNs      = createdExchange.Definition.ActionNamespace;

            _logger.LogDebug("Sending RPC message with Correlation Id: {correlationId} to Receiver Queue: {receiverQueue} " +
                             "having Action Namespace: {requestNs}.  Will receive response on Reply Queue: {replyQueueName}.",
                             correlationId,
                             receiverQueue,
                             actionNs,
                             ReplyToQueueName);
        }
        private static async Task <bool> Satisfies(IPublisherContext context, CreatedExchange createdExchange, IMessage message)
        {
            ExchangeMeta definition = createdExchange.Definition;
            bool         applies    = definition.Applies(message);

            if (applies && definition.ScriptPredicate != null)
            {
                return(await context.Scripting.SatisfiesPredicateAsync(message, definition.ScriptPredicate));
            }

            return(applies);
        }
        public async Task Publish(IPublisherContext context, CreatedExchange createdExchange,
                                  IMessage message,
                                  CancellationToken cancellationToken)
        {
            ICommand command     = (ICommand)message;
            string   contentType = createdExchange.Definition.ContentType;

            // Serialize the message and get the properties from the default-publisher to be used as
            // the initial list of message properties to which RPC specific properties will be added.
            byte[]            messageBody       = context.Serialization.Serialize(command, contentType);
            MessageProperties messageProperties = DefaultPublisherStrategy.GetMessageProperties(context, createdExchange, command);

            // Get the RPC client associated with the exchange to which the RPC message is being sent.
            IRpcClient client = context.PublisherModule.GetRpcClient(
                createdExchange.Definition.BusName,
                createdExchange.Definition.QueueMeta.QueueName);

            // Note:  Consumer replies with same content-type that was used to publish command.

            try
            {
                // Delegate to the client to send the request and wait for response in reply queue.
                byte[] resultBytes = await client.Publish(createdExchange, messageBody,
                                                          messageProperties,
                                                          cancellationToken).ConfigureAwait(false);

                // If a successful reply, deserialize the response message into the
                // result type associated with the command.
                var responseObj = context.Serialization.Deserialize(contentType, command.ResultType, resultBytes);
                command.SetResult(responseObj);

                LogReceivedRpcResponse(context, createdExchange, responseObj);
            }
            catch (RpcReplyException ex)
            {
                // If the consumer didn't supply details about the exception, then just rethrow.
                if (ex.ReplayExceptionBody == null)
                {
                    throw;
                }

                var dispatchEx = context.Serialization.Deserialize <MessageDispatchException>(contentType, ex.ReplayExceptionBody);
                context.Logger.LogError(RabbitMqLogEvents.PublisherException, dispatchEx, "RPC Exception Reply.");
                throw dispatchEx;
            }
        }
        public static MessageProperties GetMessageProperties(IPublisherContext context,
                                                             CreatedExchange createdExchange,
                                                             IMessage message)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (createdExchange == null)
            {
                throw new ArgumentNullException(nameof(createdExchange));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var definition = createdExchange.Definition;

            var props = new MessageProperties
            {
                ContentType  = definition.ContentType,
                AppId        = context.BusModule.HostAppId,
                Timestamp    = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                DeliveryMode = (byte)(definition.IsPersistent ? 2 : 1)
            };

            string correlationId = message.GetCorrelationId();

            if (correlationId != null)
            {
                props.CorrelationId = correlationId;
            }

            byte?msgPriority = message.GetPriority();

            if (msgPriority != null)
            {
                props.Priority = msgPriority.Value;
            }

            return(props);
        }
示例#8
0
        public async Task <byte[]> Publish(CreatedExchange createdExchange, byte[] messageBody,
                                           MessageProperties messageProperties,
                                           CancellationToken cancellationToken)
        {
            if (createdExchange == null)
            {
                throw new ArgumentNullException(nameof(createdExchange));
            }
            if (messageBody == null)
            {
                throw new ArgumentNullException(nameof(messageBody));
            }
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }

            AppendRpcMessageProperties(messageProperties, createdExchange);

            // Create a task that can be completed in the future when the result
            // is received in the reply queue.
            var futureResult = new TaskCompletionSource <byte[]>();

            string correlationId           = messageProperties.CorrelationId;
            int    cancelRpcRequestAfterMs = createdExchange.Definition.CancelRpcRequestAfterMs;

            var rpcPendingRequest = new RpcPendingRequest(futureResult, cancellationToken, cancelRpcRequestAfterMs);

            _pendingRpcRequests[correlationId] = rpcPendingRequest;

            string routeKey = createdExchange.Definition.QueueMeta.QueueName;

            LogRpcPublishDetails(createdExchange, correlationId);

            // Publish the command to the exchange.
            await createdExchange.Bus.Advanced.PublishAsync(createdExchange.Exchange,
                                                            routeKey,
                                                            false,
                                                            messageProperties,
                                                            messageBody).ConfigureAwait(false);

            try
            {
                // This task will be completed when the response to the command is received on
                // on the reply queue.  The task result is the bytes of the response message.
                return(await futureResult.Task);
            }
            catch (TaskCanceledException ex)
            {
                // If the pending request task has been canceled, remove the pending
                // request and unregister the cancellation delegate.
                if (_pendingRpcRequests.TryRemove(correlationId, out RpcPendingRequest pendingRequest))
                {
                    pendingRequest.UnRegister();
                }

                throw new RpcReplyException(
                          $"The RPC request with the correlation value of: {correlationId} was canceled. " +
                          $"The current timeout value is: {cancelRpcRequestAfterMs} ms.",
                          ex);
            }
            catch (Exception ex)
            {
                if (_pendingRpcRequests.TryRemove(correlationId, out RpcPendingRequest pendingRequest))
                {
                    pendingRequest.UnRegister();
                }
                throw new RpcReplyException(
                          "The RPC request with the correlation value of: {correlationId} resulted in an exception.", ex);
            }
        }