Exemple #1
0
        public Task Route(InboundBrokeredMessage inboundBrokeredMessage, TransactionContext transactionContext, ReplyToRoutingContext destinationRouterContext)
        {
            if (destinationRouterContext is null)
            {
                //TODO: log
                return(Task.CompletedTask);
            }

            try
            {
                var outbound = new OutboundBrokeredMessage(_messageIdGenerator?.GenerateId(inboundBrokeredMessage.Body).ToString(),
                                                           inboundBrokeredMessage.Body,
                                                           (IDictionary <string, object>)inboundBrokeredMessage.MessageContext,
                                                           destinationRouterContext?.DestinationPath,
                                                           inboundBrokeredMessage.BodyConverter);

                outbound.MessageContext[MessageContext.ReplyToGroupId] = destinationRouterContext.ReplyToGroupId;

                return(_router.Route(outbound, transactionContext));
            }
            catch (Exception e)
            {
                throw new ReplyToRoutingExceptions(destinationRouterContext, e);
            }
        }
        public Task SendToOutbox(OutboundBrokeredMessage outboundBrokeredMessage, TransactionContext transactionContext, CancellationToken cancellationToken = default)
        {
            Guid transactionId = Guid.NewGuid();

            if (transactionContext != null)
            {
                transactionContext.Container.TryGet <IPersistanceTransaction>(out var transaction);
                transactionId = transaction?.TransactionId ?? transactionId;
            }

            var outboxMessage = new OutboxMessage
            {
                MessageId                = outboundBrokeredMessage.MessageId,
                MessageContext           = JsonConvert.SerializeObject(outboundBrokeredMessage.MessageContext),
                Destination              = outboundBrokeredMessage.Destination,
                MessageBody              = outboundBrokeredMessage.Stringify(),
                MessageContentType       = outboundBrokeredMessage.ContentType,
                SentToOutboxAtUtc        = DateTime.UtcNow,
                ProcessedFromOutboxAtUtc = null,
                BatchId = transactionId
            };

            _logger.LogTrace($"Outbox message created for message with id: '{outboxMessage.MessageId}'");

            if (!_outbox.TryAdd(outboxMessage.MessageId, outboxMessage))
            {
                var error = $"Unable to add brokered message with id: '{outboxMessage.MessageId}' to the in memory outbox.";
                _logger.LogError(error);
                throw new InvalidOperationException(error);
            }

            _logger.LogTrace($"Outbox message with id: '{outboxMessage.MessageId}' added to the in memory outbox.");

            return(Task.CompletedTask);
        }
        public static Message AsAzureServiceBusMessage(this OutboundBrokeredMessage brokeredMessage)
        {
            var message = new Message(brokeredMessage.Body)
            {
                MessageId        = string.IsNullOrWhiteSpace(brokeredMessage.MessageId) ? Guid.NewGuid().ToString() : brokeredMessage.MessageId,
                CorrelationId    = brokeredMessage.CorrelationId,
                ContentType      = brokeredMessage.ContentType,
                Label            = brokeredMessage.GetSubject(),
                ReplyTo          = brokeredMessage.GetReplyToAddress(),
                ReplyToSessionId = brokeredMessage.GetReplyToGroupId(),
                SessionId        = brokeredMessage.GetGroupId(),
                PartitionKey     = brokeredMessage.GetPartitionKey(),
                ViaPartitionKey  = brokeredMessage.GetViaPartitionKey(),
                To = brokeredMessage.GetToAddress()
            }
            .WithUserProperties(brokeredMessage.MessageContext);

            if (brokeredMessage.GetTimeToLive() != null)
            {
                message.TimeToLive = brokeredMessage.GetTimeToLive().Value;
            }

            if (brokeredMessage.GetScheduledEnqueueTimeUtc() != null)
            {
                message.ScheduledEnqueueTimeUtc = brokeredMessage.GetScheduledEnqueueTimeUtc().Value;
            }

            return(message);
        }
        public static Message AsAzureServiceBusMessage(this OutboundBrokeredMessage brokeredMessage)
        {
            var message = new Message(brokeredMessage.Body)
            {
                CorrelationId    = brokeredMessage.GetCorrelationId(),
                ContentType      = brokeredMessage.GetContentType(),
                Label            = brokeredMessage.GetSubject(),
                ReplyTo          = brokeredMessage.GetReplyToAddress(),
                ReplyToSessionId = brokeredMessage.GetReplyToGroupId(),
                SessionId        = brokeredMessage.GetGroupId(),
                PartitionKey     = brokeredMessage.GetPartitionKey(),
                ViaPartitionKey  = brokeredMessage.GetViaPartitionKey(),
                To = brokeredMessage.GetToAddress()
            }
            .WithHashedBodyMessageId(brokeredMessage.MessageId)
            .WithUserProperties(brokeredMessage.ApplicationProperties);

            if (brokeredMessage.GetTimeToLive() != null)
            {
                message.TimeToLive = brokeredMessage.GetTimeToLive().Value;
            }

            if (brokeredMessage.GetScheduledEnqueueTimeUtc() != null)
            {
                message.ScheduledEnqueueTimeUtc = brokeredMessage.GetScheduledEnqueueTimeUtc().Value;
            }

            return(message);
        }
Exemple #5
0
        /// <summary>
        /// Routes an <see cref="OutboundBrokeredMessage"/> to the receiver via the message broker infrastructure.
        /// </summary>
        /// <param name="outboundBrokeredMessage">The outbound brokered message to be routed to the destination receiver</param>
        /// <param name="transactionContext">The contextual transaction information to be used while routing the message to its destination</param>
        /// <returns>An awaitable <see cref="Task"/></returns>
        public Task Route(OutboundBrokeredMessage outboundBrokeredMessage, TransactionContext transactionContext)
        {
            if (string.IsNullOrWhiteSpace(outboundBrokeredMessage.Destination))
            {
                throw new ArgumentNullException(nameof(outboundBrokeredMessage.Destination), $"Unable to route message with no destination path specified");
            }

            return(_brokeredMessageInfrastructureDispatcher.Dispatch(outboundBrokeredMessage, transactionContext));
        }
        public async Task SendToOutbox(OutboundBrokeredMessage outboundBrokeredMessage, TransactionContext transactionContext)
        {
            var outbox = _context.Set <OutboxMessage>();

            await SendToOutbox(outbox, outboundBrokeredMessage, transactionContext);

            await _context.SaveChangesAsync();

            _logger.LogTrace($"Outbox message added to outbox. Id: '{outboundBrokeredMessage.MessageId}'");
        }
 public static object GetApplicationPropertyByKey(this OutboundBrokeredMessage outboundBrokeredMessage, string key)
 {
     if (outboundBrokeredMessage.ApplicationProperties.TryGetValue(key, out var output))
     {
         return(output);
     }
     else
     {
         return(null);
     }
 }
        public Task Dispatch(OutboundBrokeredMessage brokeredMessage, TransactionContext transactionContext)
        {
            if (brokeredMessage == null)
            {
                throw new ArgumentNullException(nameof(brokeredMessage), $"An outgoing message is required.");
            }

            if (string.IsNullOrWhiteSpace(brokeredMessage.Destination))
            {
                throw new ArgumentNullException(nameof(brokeredMessage.Destination), $"A destination is required.");
            }

            return(Dispatch(new[] { brokeredMessage }, transactionContext));
        }
        /// <summary>
        /// Forwards an inbound brokered message to a destination
        /// </summary>
        /// <param name="inboundBrokeredMessage">The inbound brokered message to be forwarded to a receiver</param>
        /// <param name="forwardDestination">The destination path to forward the inbound brokered message to</param>
        /// <param name="transactionContext">The transactional information to use while routing</param>
        /// <returns>An awaitable <see cref="Task"/></returns>
        public Task Route(InboundBrokeredMessage inboundBrokeredMessage, string forwardDestination, TransactionContext transactionContext)
        {
            if (inboundBrokeredMessage is null)
            {
                throw new ArgumentNullException(nameof(inboundBrokeredMessage), $"An {typeof(InboundBrokeredMessage).Name} is required to be routed to the destination.");
            }

            if (string.IsNullOrWhiteSpace(forwardDestination))
            {
                return(Task.CompletedTask);
            }

            var outboundMessage = OutboundBrokeredMessage.Forward(inboundBrokeredMessage, forwardDestination)
                                  .RefreshTimeToLive();

            return(_router.Route(outboundMessage, transactionContext));
        }
Exemple #10
0
        public async Task Process(OutboxMessage message, CancellationToken cancellationToken = default)
        {
            try
            {
                IDictionary <string, object> messageContext = new Dictionary <string, object>();
                if (!string.IsNullOrWhiteSpace(message.MessageContext))
                {
                    messageContext = JsonConvert.DeserializeObject <IDictionary <string, object> >(message.MessageContext);
                }

                var contentType = message.MessageContentType;
                if (string.IsNullOrWhiteSpace(message.MessageContentType))
                {
                    contentType = (string)messageContext[MessageContext.ContentType];
                    _logger.LogTrace($"Outbox message did not contain content type. Retrieved from message context.");
                }

                messageContext.TryGetValue(MessageContext.InfrastructureType, out var infra);
                var dispatcherInfrastructure = _infrastructureProvider.GetDispatcher((string)infra);

                if (string.IsNullOrWhiteSpace(contentType))
                {
                    _logger.LogTrace($"No content type set in outbox message or message context. Unable to dispatch message.");
                    throw new ArgumentNullException(nameof(contentType), "A content type is required to serialize and send brokered message.");
                }

                var converter = _bodyConverterFactory.CreateBodyConverter(contentType);

                var outbound = new OutboundBrokeredMessage(message.MessageId, converter.GetBytes(message.MessageBody), messageContext, message.Destination, converter);
                _logger.LogTrace($"Processing message '{message.MessageId}' from outbox.");

                await((IUnitOfWork)_brokeredMessageOutbox).ExecuteAsync(async ct =>
                {
                    await _brokeredMessageOutbox.UpdateProcessedDate(message, ct);

                    await dispatcherInfrastructure.Dispatch(outbound, null);
                    _logger.LogTrace($"Message '{message.MessageId}' dispatched to messaging infrastructure from outbox.");
                }, null, cancellationToken);
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"Unable to process outbox message with id '{message.Id}'");
            }
        }
Exemple #11
0
        /// <summary>
        /// Forwards an inbound brokered message to a destination
        /// </summary>
        /// <param name="inboundBrokeredMessage">The inbound brokered message to be forwarded to a receiver</param>
        /// <param name="forwardDestination">The destination path to forward the inbound brokered message to</param>
        /// <param name="transactionContext">The transactional information to use while routing</param>
        /// <returns>An awaitable <see cref="Task"/></returns>
        public Task Route(InboundBrokeredMessage inboundBrokeredMessage, string forwardDestination, TransactionContext transactionContext)
        {
            if (inboundBrokeredMessage is null)
            {
                throw new ArgumentNullException(nameof(inboundBrokeredMessage), $"An {typeof(InboundBrokeredMessage).Name} is required to be routed to the destination.");
            }

            if (string.IsNullOrWhiteSpace(forwardDestination))
            {
                return(Task.CompletedTask);
            }

            var outboundMessage = new OutboundBrokeredMessage(_messageIdGenerator?.GenerateId(inboundBrokeredMessage.Body).ToString(),
                                                              inboundBrokeredMessage.Body,
                                                              (IDictionary <string, object>)inboundBrokeredMessage.MessageContext,
                                                              forwardDestination,
                                                              inboundBrokeredMessage.BodyConverter);

            return(_router.Route(outboundMessage, transactionContext));
        }
Exemple #12
0
        public Task Route(InboundBrokeredMessage inboundBrokeredMessage, TransactionContext transactionContext, ReplyToRoutingContext destinationRouterContext)
        {
            if (destinationRouterContext is null)
            {
                //TODO: log
                return(Task.CompletedTask);
            }

            try
            {
                var outbound = OutboundBrokeredMessage.Forward(inboundBrokeredMessage, destinationRouterContext?.DestinationPath);
                outbound.ApplicationProperties[ApplicationProperties.ReplyToGroupId] = destinationRouterContext.ReplyToGroupId;

                return(_router.Route(outbound, transactionContext));
            }
            catch (Exception e)
            {
                throw new ReplyToRoutingExceptions(destinationRouterContext, e);
            }
        }
        private async Task SendToOutbox(DbSet <OutboxMessage> outbox, OutboundBrokeredMessage outboundBrokeredMessage, TransactionContext transactionContext)
        {
            var  currentTransaction = transactionContext?.Container.GetOrAdd <IPersistanceTransaction>();
            Guid transactionId      = currentTransaction?.TransactionId ?? Guid.Empty;

            //TODO: trim the OutboxMessage object down. likely dont need Body, etc.
            var outboxMessage = new OutboxMessage
            {
                MessageId = outboundBrokeredMessage.MessageId,
                StringifiedApplicationProperties = JsonConvert.SerializeObject(outboundBrokeredMessage.ApplicationProperties),
                Body                     = outboundBrokeredMessage.Body,
                Destination              = outboundBrokeredMessage.Destination,
                StringifiedMessage       = outboundBrokeredMessage.Stringify(),
                SentToOutboxAtUtc        = DateTime.UtcNow,
                ProcessedFromOutboxAtUtc = null,
                BatchId                  = transactionId
            };

            _logger.LogTrace($"Outbox message created for message with id: '{outboxMessage.MessageId}'");

            await outbox.AddAsync(outboxMessage);
        }
Exemple #14
0
        private async Task SendToOutboxImpl(DbSet <OutboxMessage> outbox, OutboundBrokeredMessage outboundBrokeredMessage, TransactionContext transactionContext, CancellationToken cancellationToken = default)
        {
            var  currentTransaction = transactionContext?.Container.GetOrDefault <IPersistanceTransaction>();
            Guid transactionId      = currentTransaction?.TransactionId ?? Guid.Empty;

            var outboxMessage = new OutboxMessage
            {
                MessageId                = outboundBrokeredMessage.MessageId,
                MessageContext           = JsonConvert.SerializeObject(outboundBrokeredMessage.MessageContext),
                Destination              = outboundBrokeredMessage.Destination,
                MessageBody              = outboundBrokeredMessage.Stringify(),
                MessageContentType       = outboundBrokeredMessage.ContentType,
                SentToOutboxAtUtc        = DateTime.UtcNow,
                ProcessedFromOutboxAtUtc = null,
                BatchId = transactionId
            };

            _logger.LogTrace($"Outbox message created. MessageId: '{outboxMessage.MessageId}', BatchId: {outboxMessage.BatchId}");

            await outbox.AddAsync(outboxMessage, cancellationToken).ConfigureAwait(false);

            _logger.LogTrace($"Outbox message added to outbox. MessageId: '{outboxMessage.MessageId}', BatchId: {outboxMessage.BatchId}");
        }
        /// <summary>
        /// Routes a brokered message to a brokered message receiver responsible for compensating a received message
        /// </summary>
        /// <param name="inboundBrokeredMessage">The inbound brokered message to be routed to the compensation destination</param>
        /// <param name="transactionContext">The transaction information that was received with <paramref name="inboundBrokeredMessage"/></param>
        /// <param name="destinationRouterContext">The <see cref="CompensationRoutingContext"/> containing contextual information describing the compensating action</param>
        /// <exception cref="CompensationRoutingException">An exception containing contextual information describing the failure during compensation and routing details</exception>
        /// <returns>An awaitable <see cref="Task"/></returns>
        public Task Route(InboundBrokeredMessage inboundBrokeredMessage, TransactionContext transactionContext, CompensationRoutingContext destinationRouterContext)
        {
            if (destinationRouterContext is null)
            {
                //TODO: log
                return(Task.CompletedTask);
            }

            try
            {
                if (destinationRouterContext is null)
                {
                    throw new ArgumentNullException(nameof(destinationRouterContext), $"A '{typeof(CompensationRoutingContext).Name}' is required to route a compensation message");
                }

                if (string.IsNullOrWhiteSpace(destinationRouterContext.CompensateDetails))
                {
                    throw new ArgumentNullException(nameof(destinationRouterContext.CompensateDetails), $"A compensation reason is required to route a compensation message");
                }

                if (string.IsNullOrWhiteSpace(destinationRouterContext.CompensateDescription))
                {
                    throw new ArgumentNullException(nameof(destinationRouterContext.CompensateDescription), $"A compensation description is required to route a compensation message");
                }

                var outbound = OutboundBrokeredMessage.Forward(inboundBrokeredMessage, destinationRouterContext.DestinationPath)
                               .WithFailureDetails(destinationRouterContext.CompensateDetails)
                               .WithFailureDescription(destinationRouterContext.CompensateDescription)
                               .SetFailure();

                return(_router.Route(outbound, transactionContext));
            }
            catch (Exception causeOfRoutingFailure)
            {
                throw new CompensationRoutingException(destinationRouterContext, causeOfRoutingFailure);
            }
        }
 public static OutboundBrokeredMessage WithPartitionKey(this OutboundBrokeredMessage outboundBrokeredMessage, string partitionKey)
 {
     outboundBrokeredMessage.ApplicationProperties[ASBHeaders.PartitionKey] = partitionKey;
     return(outboundBrokeredMessage);
 }
 public static string GetToAddress(this OutboundBrokeredMessage outboundBrokeredMessage)
 {
     return((string)outboundBrokeredMessage.GetApplicationPropertyByKey(ASBHeaders.To));
 }
 public static OutboundBrokeredMessage WithTo(this OutboundBrokeredMessage outboundBrokeredMessage, string to)
 {
     outboundBrokeredMessage.ApplicationProperties[ASBHeaders.To] = to;
     return(outboundBrokeredMessage);
 }
 public static DateTime?GetScheduledEnqueueTimeUtc(this OutboundBrokeredMessage outboundBrokeredMessage)
 {
     return((DateTime?)outboundBrokeredMessage.GetApplicationPropertyByKey(ASBHeaders.ScheduledEnqueueTimeUtc));
 }
 public static OutboundBrokeredMessage WithScheduledEnqueueTimeUtc(this OutboundBrokeredMessage outboundBrokeredMessage, DateTime scheduledEnqueueTimeUtc)
 {
     outboundBrokeredMessage.ApplicationProperties[ASBHeaders.ScheduledEnqueueTimeUtc] = scheduledEnqueueTimeUtc;
     return(outboundBrokeredMessage);
 }
Exemple #21
0
 public Task Dispatch(OutboundBrokeredMessage brokeredMessage, TransactionContext transactionContext)
 => Dispatch(new[] { brokeredMessage }, transactionContext);
Exemple #22
0
 private Task <Guid> BeginConversation(SqlConnection connection, SqlTransaction transaction, OutboundBrokeredMessage brokeredMessage, object initiatorService, object serviceContractName)
 => new BeginDialogConversationCommand(connection, brokeredMessage.Destination, (string)initiatorService, (string)serviceContractName, _options.ConversationLifetimeInSeconds, transaction: transaction).ExecuteAsync();
 public static string GetPartitionKey(this OutboundBrokeredMessage outboundBrokeredMessage)
 {
     return((string)outboundBrokeredMessage.GetApplicationPropertyByKey(ASBHeaders.PartitionKey));
 }
 public static string GetSubject(this OutboundBrokeredMessage outboundBrokeredMessage) => outboundBrokeredMessage.GetMessageContextByKey <string>(MessageContext.Subject);
 public static string GetGroupId(this OutboundBrokeredMessage outboundBrokeredMessage) => outboundBrokeredMessage.GetMessageContextByKey <string>(MessageContext.GroupId);
 public static string GetToAddress(this OutboundBrokeredMessage outboundBrokeredMessage) => (string)outboundBrokeredMessage.GetMessageContextByKey(ASBMessageContext.To);
 public static string GetPartitionKey(this OutboundBrokeredMessage outboundBrokeredMessage) => outboundBrokeredMessage.GetMessageContextByKey <string>(ASBMessageContext.PartitionKey);
 public static OutboundBrokeredMessage WithPartitionKey(this OutboundBrokeredMessage outboundBrokeredMessage, string partitionKey)
 {
     outboundBrokeredMessage.MessageContext[ASBMessageContext.PartitionKey] = partitionKey;
     return(outboundBrokeredMessage);
 }
 public static string GetReplyToAddress(this OutboundBrokeredMessage outboundBrokeredMessage) => outboundBrokeredMessage.GetMessageContextByKey <string>(MessageContext.ReplyToAddress);
Exemple #30
0
        private Task SendMessageOnConversation(SqlConnection connection, SqlTransaction transaction, OutboundBrokeredMessage brokeredMessage, string messageTypeName, Guid newConvHandle)
        {
            byte[] message = brokeredMessage.Body;
            if (messageTypeName == ServicesMessageTypes.ChatterBrokeredMessageType)
            {
                var bodyConverter = _bodyConverterFactory.CreateBodyConverter(_options.MessageBodyType);
                message = bodyConverter.Convert(brokeredMessage);
            }

            return(new SendOnConversationCommand(connection, newConvHandle, message, transaction, _options.CompressMessageBody, messageTypeName).ExecuteAsync());
        }