protected override async Task Terminate(IInvokeHandlerContext context)
        {
            if (context.Extensions.TryGet(out ActiveSagaInstance saga) && saga.NotFound && saga.Metadata.SagaType == context.MessageHandler.Instance.GetType())
            {
                return;
            }

            var messageHandler = context.MessageHandler;

            var startTime = DateTimeOffset.UtcNow;

            try
            {
                await messageHandler
                .Invoke(context.MessageBeingHandled, context)
                .ThrowIfNull()
                .ConfigureAwait(false);
            }
            catch (Exception e)
            {
                e.Data["Message type"]         = context.MessageMetadata.MessageType.FullName;
                e.Data["Handler type"]         = context.MessageHandler.HandlerType.FullName;
                e.Data["Handler start time"]   = DateTimeOffsetHelper.ToWireFormattedString(startTime);
                e.Data["Handler failure time"] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                throw;
            }
        }
        protected override Task Terminate(ISubscribeContext context)
        {
            var eventType = context.EventType;

            var publisherAddresses = subscriptionRouter.GetAddressesForEventType(eventType);

            if (publisherAddresses.Count == 0)
            {
                throw new Exception($"No publisher address could be found for message type '{eventType}'. Ensure that a publisher has been configured for the event type and that the configured publisher endpoint has at least one known instance.");
            }

            var subscribeTasks = new List <Task>(publisherAddresses.Count);

            foreach (var publisherAddress in publisherAddresses)
            {
                Logger.Debug($"Subscribing to {eventType.AssemblyQualifiedName} at publisher queue {publisherAddress}");

                var subscriptionMessage = ControlMessageFactory.Create(MessageIntentEnum.Subscribe);

                subscriptionMessage.Headers[Headers.SubscriptionMessageType]    = eventType.AssemblyQualifiedName;
                subscriptionMessage.Headers[Headers.ReplyToAddress]             = subscriberAddress;
                subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = subscriberAddress;
                subscriptionMessage.Headers[Headers.SubscriberEndpoint]         = subscriberEndpoint;
                subscriptionMessage.Headers[Headers.TimeSent]           = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                subscriptionMessage.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch;

                subscribeTasks.Add(SendSubscribeMessageWithRetries(publisherAddress, subscriptionMessage, eventType.AssemblyQualifiedName, context.Extensions));
            }
            return(Task.WhenAll(subscribeTasks));
        }
예제 #3
0
        protected override async Task Terminate(IUnsubscribeContext context)
        {
            var eventType     = context.EventType;
            var eventMetadata = messageMetadataRegistry.GetMessageMetadata(eventType);

            await subscriptionManager.Unsubscribe(eventMetadata, context.Extensions, context.CancellationToken).ConfigureAwait(false);


            var publisherAddresses = subscriptionRouter.GetAddressesForEventType(eventType);

            if (publisherAddresses.Count == 0)
            {
                return;
            }

            var unsubscribeTasks = new List <Task>(publisherAddresses.Count);

            foreach (var publisherAddress in publisherAddresses)
            {
                Logger.Debug("Unsubscribing to " + eventType.AssemblyQualifiedName + " at publisher queue " + publisherAddress);

                var unsubscribeMessage = ControlMessageFactory.Create(MessageIntentEnum.Unsubscribe);

                unsubscribeMessage.Headers[Headers.SubscriptionMessageType]    = eventType.AssemblyQualifiedName;
                unsubscribeMessage.Headers[Headers.ReplyToAddress]             = replyToAddress;
                unsubscribeMessage.Headers[Headers.SubscriberTransportAddress] = replyToAddress;
                unsubscribeMessage.Headers[Headers.SubscriberEndpoint]         = endpoint;
                unsubscribeMessage.Headers[Headers.TimeSent]           = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                unsubscribeMessage.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch;

                unsubscribeTasks.Add(SendUnsubscribeMessageWithRetries(publisherAddress, unsubscribeMessage, eventType.AssemblyQualifiedName, context.Extensions, 0, context.CancellationToken));
            }

            await Task.WhenAll(unsubscribeTasks).ConfigureAwait(false);
        }
        public async Task Invoke(IIncomingPhysicalMessageContext context, Func <IIncomingPhysicalMessageContext, Task> next)
        {
            var state = new State();

            var headers = context.Message.Headers;

            if (headers.TryGetValue(Headers.TimeSent, out var timeSentString))
            {
                state.TimeSent = DateTimeOffsetHelper.ToDateTimeOffset(timeSentString);
            }

            state.ProcessingStarted = DateTimeOffset.UtcNow;
            context.Extensions.Set(state);
            var stopwatch = Stopwatch.StartNew();

            try
            {
                await next(context).ConfigureAwait(false);
            }
            finally
            {
                stopwatch.Stop();
                state.ProcessingEnded = state.ProcessingStarted + stopwatch.Elapsed;
            }
        }
        protected override async Task Terminate(IInvokeHandlerContext context)
        {
            if (context.Extensions.TryGet(out ActiveSagaInstance saga) && saga.NotFound && saga.Metadata.SagaType == context.MessageHandler.Instance.GetType())
            {
                return;
            }

            var messageHandler = context.MessageHandler;

            // Might as well abort before invoking the handler if we're shutting down
            context.CancellationToken.ThrowIfCancellationRequested();

            var startTime = DateTimeOffset.UtcNow;

            try
            {
                await messageHandler
                .Invoke(context.MessageBeingHandled, context)
                .ThrowIfNull()
                .ConfigureAwait(false);
            }
#pragma warning disable PS0019 // Do not catch Exception without considering OperationCanceledException - enriching and rethrowing
            catch (Exception ex)
#pragma warning restore PS0019 // Do not catch Exception without considering OperationCanceledException
            {
                ex.Data["Message type"]         = context.MessageMetadata.MessageType.FullName;
                ex.Data["Handler type"]         = context.MessageHandler.HandlerType.FullName;
                ex.Data["Handler start time"]   = DateTimeOffsetHelper.ToWireFormattedString(startTime);
                ex.Data["Handler failure time"] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                ex.Data["Handler canceled"]     = context.CancellationToken.IsCancellationRequested;
                throw;
            }
        }
예제 #6
0
        public static void SetExceptionHeaders(Dictionary <string, string> headers, Exception e)
        {
            headers["NServiceBus.ExceptionInfo.ExceptionType"] = e.GetType().FullName;

            if (e.InnerException != null)
            {
                headers["NServiceBus.ExceptionInfo.InnerExceptionType"] = e.InnerException.GetType().FullName;
            }

            headers["NServiceBus.ExceptionInfo.HelpLink"]   = e.HelpLink;
            headers["NServiceBus.ExceptionInfo.Message"]    = e.GetMessage().Truncate(16384);
            headers["NServiceBus.ExceptionInfo.Source"]     = e.Source;
            headers["NServiceBus.ExceptionInfo.StackTrace"] = e.ToString();
            headers["NServiceBus.TimeOfFailure"]            = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);

            if (e.Data == null)
            {
                return;
            }
#pragma warning disable DE0006
            foreach (DictionaryEntry entry in e.Data)
#pragma warning restore DE0006
            {
                if (entry.Value == null)
                {
                    continue;
                }
                headers["NServiceBus.ExceptionInfo.Data." + entry.Key] = entry.Value.ToString();
            }
        }
        static bool HasReachedMaxTime(IncomingMessage message)
        {
            if (!message.Headers.TryGetValue(Headers.DelayedRetriesTimestamp, out var timestampHeader))
            {
                return(false);
            }

            if (string.IsNullOrEmpty(timestampHeader))
            {
                return(false);
            }

            try
            {
                var handledAt = DateTimeOffsetHelper.ToDateTimeOffset(timestampHeader);

                var now = DateTimeOffset.UtcNow;
                if (now > handledAt.AddDays(1))
                {
                    return(true);
                }
            }
            // this code won't usually throw but in case a user has decided to hack a message/headers and for some bizarre reason
            // they changed the date and that parse fails, we want to make sure that doesn't prevent the message from being
            // forwarded to the error queue.
            catch (Exception)
            {
            }

            return(false);
        }
예제 #8
0
        protected override async Task Terminate(ISubscribeContext context)
        {
            var eventType = context.EventType;

            await subscriptionManager.Subscribe(eventType, context.Extensions).ConfigureAwait(false);

            var publisherAddresses = subscriptionRouter.GetAddressesForEventType(eventType);

            if (publisherAddresses.Count == 0)
            {
                return;
            }

            var subscribeTasks = new List <Task>(publisherAddresses.Count);

            foreach (var publisherAddress in publisherAddresses)
            {
                Logger.Debug($"Subscribing to {eventType.AssemblyQualifiedName} at publisher queue {publisherAddress}");

                var subscriptionMessage = ControlMessageFactory.Create(MessageIntentEnum.Subscribe);

                subscriptionMessage.Headers[Headers.SubscriptionMessageType]    = eventType.AssemblyQualifiedName;
                subscriptionMessage.Headers[Headers.ReplyToAddress]             = subscriberAddress;
                subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = subscriberAddress;
                subscriptionMessage.Headers[Headers.SubscriberEndpoint]         = subscriberEndpoint;
                subscriptionMessage.Headers[Headers.TimeSent]           = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                subscriptionMessage.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch;

                subscribeTasks.Add(SendSubscribeMessageWithRetries(publisherAddress, subscriptionMessage, eventType.AssemblyQualifiedName, context.Extensions));
            }

            await Task.WhenAll(subscribeTasks).ConfigureAwait(false);
        }
        protected override async Task Terminate(ISubscribeContext context)
        {
            var subscribeTasks = new List <Task>();

            foreach (var eventType in context.EventTypes)
            {
                try
                {
                    var publisherAddresses = subscriptionRouter.GetAddressesForEventType(eventType);
                    if (publisherAddresses.Count == 0)
                    {
                        throw new Exception($"No publisher address could be found for message type '{eventType}'. Ensure that a publisher has been configured for the event type and that the configured publisher endpoint has at least one known instance.");
                    }

                    foreach (var publisherAddress in publisherAddresses)
                    {
                        Logger.Debug($"Subscribing to {eventType.AssemblyQualifiedName} at publisher queue {publisherAddress}");

                        var subscriptionMessage = ControlMessageFactory.Create(MessageIntentEnum.Subscribe);

                        subscriptionMessage.Headers[Headers.SubscriptionMessageType]    = eventType.AssemblyQualifiedName;
                        subscriptionMessage.Headers[Headers.ReplyToAddress]             = subscriberAddress;
                        subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = subscriberAddress;
                        subscriptionMessage.Headers[Headers.SubscriberEndpoint]         = subscriberEndpoint;
                        subscriptionMessage.Headers[Headers.TimeSent]           = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                        subscriptionMessage.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch;

                        subscribeTasks.Add(SendSubscribeMessageWithRetries(publisherAddress, subscriptionMessage, eventType.AssemblyQualifiedName, context.Extensions, 0, context.CancellationToken));
                    }
                }
#pragma warning disable PS0019 // Do not catch Exception without considering OperationCanceledException - Tasks are not observed until below
                catch (Exception e)
#pragma warning restore PS0019 // Do not catch Exception without considering OperationCanceledException
                {
                    subscribeTasks.Add(Task.FromException(e));
                }
            }

            var t = Task.WhenAll(subscribeTasks);
            try
            {
                await t.ConfigureAwait(false);
            }
            catch (Exception)
            {
                // if subscribing via SubscribeAll, throw an AggregateException
                if (context.Extensions.TryGet <bool>(MessageSession.SubscribeAllFlagKey, out var flag) && flag)
                {
                    throw t.Exception;
                }

                // otherwise throw the first exception to not change exception behavior when calling subscribe.
                throw;
            }
        }
        public Task Invoke(IAuditContext context, Func <IAuditContext, Task> next)
        {
            if (context.Extensions.TryGet(out ProcessingStatisticsBehavior.State state))
            {
                context.AddAuditData(Headers.ProcessingStarted, DateTimeOffsetHelper.ToWireFormattedString(state.ProcessingStarted));
                // We can't take the processing time from the state since we don't know it yet.
                context.AddAuditData(Headers.ProcessingEnded, DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow));
            }

            return(next(context));
        }
예제 #11
0
        public Task Invoke(IRoutingContext context, Func <IRoutingContext, Task> next)
        {
            var message = context.Message;

            if (!message.Headers.ContainsKey(Headers.NServiceBusVersion))
            {
                message.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch;
            }

            if (!message.Headers.ContainsKey(Headers.TimeSent))
            {
                message.Headers[Headers.TimeSent] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
            }
            return(next(context));
        }
예제 #12
0
        static List <DeliveryConstraint> DeserializeConstraints(Dictionary <string, string> options)
        {
            var constraints = new List <DeliveryConstraint>(4);

            if (options.TryGetValue("DeliverAt", out var deliverAt))
            {
                constraints.Add(new DoNotDeliverBefore(DateTimeOffsetHelper.ToDateTimeOffset(deliverAt)));
            }

            if (options.TryGetValue("DelayDeliveryFor", out var delay))
            {
                constraints.Add(new DelayDeliveryWith(TimeSpan.Parse(delay)));
            }

            if (options.TryGetValue("TimeToBeReceived", out var ttbr))
            {
                constraints.Add(new DiscardIfNotReceivedBefore(TimeSpan.Parse(ttbr)));
            }
            return(constraints);
        }
예제 #13
0
        static void SerializeDeliveryConstraint(DeliveryConstraint constraint, Dictionary <string, string> options)
        {
            if (constraint is DoNotDeliverBefore doNotDeliverBefore)
            {
                options["DeliverAt"] = DateTimeOffsetHelper.ToWireFormattedString(doNotDeliverBefore.At);
                return;
            }

            if (constraint is DelayDeliveryWith delayDeliveryWith)
            {
                options["DelayDeliveryFor"] = delayDeliveryWith.Delay.ToString();
                return;
            }

            if (constraint is DiscardIfNotReceivedBefore discard)
            {
                options["TimeToBeReceived"] = discard.MaxTime.ToString();
                return;
            }

            throw new Exception($"Unknown delivery constraint {constraint.GetType().FullName}");
        }
예제 #14
0
 public static void SetDelayedDeliveryTimestamp(this OutgoingMessage message, DateTimeOffset timestamp)
 {
     message.Headers[Headers.DelayedRetriesTimestamp] = DateTimeOffsetHelper.ToWireFormattedString(timestamp);
 }
        protected override async Task Terminate(ISubscribeContext context)
        {
            var eventMetadata = new MessageMetadata[context.EventTypes.Length];

            for (int i = 0; i < context.EventTypes.Length; i++)
            {
                eventMetadata[i] = messageMetadataRegistry.GetMessageMetadata(context.EventTypes[i]);
            }
            try
            {
                await subscriptionManager.SubscribeAll(eventMetadata, context.Extensions, context.CancellationToken).ConfigureAwait(false);
            }
            catch (AggregateException e)
            {
                if (context.Extensions.TryGet <bool>(MessageSession.SubscribeAllFlagKey, out var flag) && flag)
                {
                    throw;
                }

                // if this is called from Subscribe, rethrow the expected single exception
                throw e.InnerException ?? e;
            }

            var subscribeTasks = new List <Task>();

            foreach (var eventType in context.EventTypes)
            {
                try
                {
                    var publisherAddresses = subscriptionRouter.GetAddressesForEventType(eventType);
                    if (publisherAddresses.Count == 0)
                    {
                        continue;
                    }

                    foreach (var publisherAddress in publisherAddresses)
                    {
                        Logger.Debug($"Subscribing to {eventType.AssemblyQualifiedName} at publisher queue {publisherAddress}");

                        var subscriptionMessage = ControlMessageFactory.Create(MessageIntentEnum.Subscribe);

                        subscriptionMessage.Headers[Headers.SubscriptionMessageType]    = eventType.AssemblyQualifiedName;
                        subscriptionMessage.Headers[Headers.ReplyToAddress]             = subscriberAddress;
                        subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = subscriberAddress;
                        subscriptionMessage.Headers[Headers.SubscriberEndpoint]         = subscriberEndpoint;
                        subscriptionMessage.Headers[Headers.TimeSent]           = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow);
                        subscriptionMessage.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch;

                        subscribeTasks.Add(SendSubscribeMessageWithRetries(publisherAddress, subscriptionMessage, eventType.AssemblyQualifiedName, context.Extensions, 0, context.CancellationToken));
                    }
                }
#pragma warning disable PS0019 // Do not catch Exception without considering OperationCanceledException - Tasks are not observed until below
                catch (Exception e)
#pragma warning restore PS0019 // Do not catch Exception without considering OperationCanceledException
                {
                    subscribeTasks.Add(Task.FromException(e));
                }
            }

            var t = Task.WhenAll(subscribeTasks);
            try
            {
                await t.ConfigureAwait(false);
            }
            catch (Exception)
            {
                // if subscribing via SubscribeAll, throw an AggregateException
                if (context.Extensions.TryGet <bool>(MessageSession.SubscribeAllFlagKey, out var flag) && flag)
                {
                    throw t.Exception;
                }

                // otherwise throw the first exception to not change exception behavior when calling subscribe.
                throw;
            }
        }