Ejemplo n.º 1
0
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var message = context.Load <Message>();
            var args    = new MessageHandledEventHandlerArgs();
            var bus     = _bus.Value;

            foreach (var e in _beforeMessageHandled)
            {
                e(bus, message.Headers, message.Body, context, args);
            }

            try
            {
                await next();

                foreach (var e in _afterMessageHandled)
                {
                    e(bus, message.Headers, message.Body, context, args);
                }
            }
            catch (Exception exception)
            {
                context.Save(exception);

                foreach (var e in _afterMessageHandled)
                {
                    e(bus, message.Headers, message.Body, context, args);
                }

                if (!args.IgnoreException)
                {
                    throw;
                }
            }
        }
Ejemplo n.º 2
0
        public async Task Given_incoming_step_context_has_sequence_it_should_increment(int?incomingSequenceNr, int expectedOutgoingSequenceNr)
        {
            var incomingHeaders = new Dictionary <string, string>();

            if (incomingSequenceNr.HasValue)
            {
                incomingHeaders.Add(Headers.CorrelationSequence, incomingSequenceNr.ToString());
            }
            var incomingStepContext = new IncomingStepContext(
                new TransportMessage(
                    incomingHeaders, new byte[0]),
                _transactionContextMock.Object
                );

            incomingStepContext.Save(new Message(incomingHeaders, new { }));
            _stepContext.Save(incomingStepContext);

            // Act
            await _sut.Process(_stepContext, _next);

            // Assert
            _messageHeaders
            .Should().ContainKey(Headers.CorrelationSequence)
            .WhichValue
            .Should().Be(expectedOutgoingSequenceNr.ToString());
        }
Ejemplo n.º 3
0
        void PossiblyDecompressTransportMessage(IncomingStepContext context)
        {
            var transportMessage = context.Load <TransportMessage>();

            string contentEncoding;

            if (!transportMessage.Headers.TryGetValue(Headers.ContentEncoding, out contentEncoding))
            {
                return;
            }

            if (contentEncoding != ZipMessagesOutgoingStep.GzipEncodingHeader)
            {
                var message = $"The message {transportMessage.GetMessageLabel()} has a '{Headers.ContentEncoding}' with the" +
                              $" value '{contentEncoding}', but this middleware only knows how to decompress" +
                              $" '{ZipMessagesOutgoingStep.GzipEncodingHeader}'";

                throw new ArgumentException(message);
            }

            var headers        = transportMessage.Headers.Clone();
            var compressedBody = transportMessage.Body;

            headers.Remove(Headers.ContentEncoding);

            var body = _zipper.Unzip(compressedBody);

            context.Save(new TransportMessage(headers, body));
        }
Ejemplo n.º 4
0
            public async Task Process(IncomingStepContext context, Func <Task> next)
            {
                var serviceProvider = context.Load <IServiceProvider>();

                SomethingDisposable somethingDisposable;

                using (var scope = serviceProvider.CreateScope())
                {
                    context.Save(scope);

                    somethingDisposable = scope.ServiceProvider.GetRequiredService <SomethingDisposable>();

                    Assert.That(somethingDisposable.HasBeenDisposed, Is.False);

                    var somethingDisposableResolvedAgain = scope.ServiceProvider.GetRequiredService <SomethingDisposable>();

                    Assert.That(somethingDisposableResolvedAgain, Is.SameAs(somethingDisposable));

                    await next();

                    var somethingDisposableInjectedIntoMessageHandler = context.Load <SomethingDisposable>();

                    Assert.That(somethingDisposableInjectedIntoMessageHandler, Is.SameAs(somethingDisposable));

                    Assert.That(somethingDisposable.HasBeenDisposed, Is.False);
                }

                Assert.That(somethingDisposable.HasBeenDisposed, Is.True);
            }
Ejemplo n.º 5
0
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            // stashes the current implementation of IDataBusStorage in the context for DataBusAttachment to find
            context.Save(DataBusStorageKey, _dataBusStorage);

            await next().ConfigureAwait(false);
        }
Ejemplo n.º 6
0
        async Task ProcessMessage(TransactionContext context, TransportMessage transportMessage)
        {
            try
            {
                var stepContext = new IncomingStepContext(transportMessage, context);

                stepContext.Save(_busDisposalCancellationToken);

                await _pipelineInvoker.Invoke(stepContext);

                try
                {
                    await context.Complete();
                }
                catch (Exception exception)
                {
                    _log.Error(exception, "An error occurred when attempting to complete the transaction context");
                }
            }
            catch (OperationCanceledException exception)
            {
                context.Abort();

                _log.Error(exception, "Worker was aborted while handling message {messageLabel}", transportMessage.GetMessageLabel());
            }
            catch (Exception exception)
            {
                context.Abort();

                _log.Error(exception, "Unhandled exception while handling message {messageLabel}", transportMessage.GetMessageLabel());
            }
        }
 /// <summary>
 /// Deserializes the incoming message by invoking the currently configured <see cref="ISerializer"/> on the <see cref="TransportMessage"/> found in the context,
 /// storing the result as the <see cref="Message"/> returned by the serializer
 /// </summary>
 public async Task Process(IncomingStepContext context, Func<Task> next)
 {
     var transportMessage = context.Load<TransportMessage>();
     var message = await _serializer.Deserialize(transportMessage);
     context.Save(message);
     await next();
 }
Ejemplo n.º 8
0
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var message = context.Load <Message>();
            var headers = message.Headers;

            if (headers.ContainsKey(MapLegacyHeadersIncomingStep.LegacyMessageHeader))
            {
                var body  = message.Body;
                var array = body as object[];

                if (array == null)
                {
                    throw new FormatException(
                              $"Incoming message has the '{MapLegacyHeadersIncomingStep.LegacyMessageHeader}' header, but the message body {body} is not an object[] as expected");
                }

                foreach (var bodyToDispatch in array)
                {
                    var messageBodyToDispatch = PossiblyConvertBody(bodyToDispatch, headers);

                    context.Save(new Message(headers, messageBodyToDispatch));

                    await next();
                }

                return;
            }

            await next();
        }
        /// <summary>
        /// Deserializes the incoming message by invoking the currently configured <see cref="ISerializer"/> on the <see cref="TransportMessage"/> found in the context,
        /// storing the result as the <see cref="Message"/> returned by the serializer
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transportMessage = context.Load <TransportMessage>();
            var message          = await _serializer.Deserialize(transportMessage);

            context.Save(message);
            await next();
        }
Ejemplo n.º 10
0
        static IncomingStepContext GetIncomingStepContext()
        {
            var transportMessage   = new TransportMessage(new Dictionary <string, string>(), new byte[] { 1, 2, 3 });
            var transactionContext = new TransactionContext();
            var context            = new IncomingStepContext(transportMessage, transactionContext);

            context.Save(new List <string>());
            return(context);
        }
Ejemplo n.º 11
0
    public Task Process(IncomingStepContext context, Func <Task> next)
    {
        var message         = context.Load <Message>();
        var handlerInvokers = context.Load <HandlerInvokers>().ToList();

        handlerInvokers.RemoveAll(x => x.Handler.GetType() == typeof(RebusDistributedEventHandlerAdapter <object>));
        context.Save(new HandlerInvokers(message, handlerInvokers));

        return(next());
    }
Ejemplo n.º 12
0
        /// <summary>
        /// Reorders the handler invokers if necessary
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var handlerInvokers        = context.Load <HandlerInvokers>();
            var orderedHandlerInvokers = handlerInvokers.OrderBy(i => _configuration.GetIndex(i.Handler));
            var newHandlerInvokers     = new HandlerInvokers(orderedHandlerInvokers);

            context.Save(newHandlerInvokers);

            await next();
        }
        void MutateLegacyTransportMessage(IncomingStepContext context, Dictionary <string, string> headers, TransportMessage transportMessage)
        {
            var newHeaders = MapTrivialHeaders(headers);

            MapSpecialHeaders(newHeaders);

            newHeaders[LegacyMessageHeader] = "";

            context.Save(new TransportMessage(newHeaders, transportMessage.Body));
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Executes the entire message processing pipeline in an exception handler, tracking the number of failed delivery attempts.
        /// Forwards the message to the error queue when the max number of delivery attempts has been exceeded.
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transportMessage   = context.Load <TransportMessage>();
            var transactionContext = context.Load <ITransactionContext>();
            var messageId          = transportMessage.Headers.GetValueOrNull(Headers.MessageId);

            if (string.IsNullOrWhiteSpace(messageId))
            {
                await MoveMessageToErrorQueue("<no message ID>", transportMessage,
                                              transactionContext, string.Format("Received message with empty or absent '{0}' header! All messages must be" +
                                                                                " supplied with an ID . If no ID is present, the message cannot be tracked" +
                                                                                " between delivery attempts, and other stuff would also be much harder to" +
                                                                                " do - therefore, it is a requirement that messages be supplied with an ID.",
                                                                                Headers.MessageId),
                                              shortErrorDescription : string.Format("Received message with empty or absent '{0}' header", Headers.MessageId));

                return;
            }

            if (_errorTracker.HasFailedTooManyTimes(messageId))
            {
                // if we don't have 2nd level retries, just get the message out of the way
                if (!_simpleRetryStrategySettings.SecondLevelRetriesEnabled)
                {
                    await
                    MoveMessageToErrorQueue(messageId, transportMessage, transactionContext,
                                            GetErrorDescriptionFor(messageId), GetErrorDescriptionFor(messageId, brief : true));

                    _errorTracker.CleanUp(messageId);
                    return;
                }

                // change the identifier to track by to perform this 2nd level of delivery attempts
                var secondLevelMessageId = messageId + "-2nd-level";

                if (_errorTracker.HasFailedTooManyTimes(secondLevelMessageId))
                {
                    await
                    MoveMessageToErrorQueue(messageId, transportMessage, transactionContext,
                                            GetErrorDescriptionFor(messageId), GetErrorDescriptionFor(messageId, brief : true));

                    _errorTracker.CleanUp(messageId);
                    _errorTracker.CleanUp(secondLevelMessageId);
                    return;
                }

                context.Save(DispatchAsFailedMessageKey, true);

                await DispatchWithTrackerIdentifier(next, secondLevelMessageId, transactionContext);

                return;
            }

            await DispatchWithTrackerIdentifier(next, messageId, transactionContext);
        }
Ejemplo n.º 15
0
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transportMessage = context.Load <TransportMessage>();

            if (StandardAdapter.IsUsableOnIncoming(transportMessage, StandardHeaderOptions))
            {
                transportMessage = StandardAdapter.ConvertIncomingTransportMessage(transportMessage, StandardHeaderOptions);
                context.Save(transportMessage);
            }

            await next();
        }
Ejemplo n.º 16
0
    /// <summary>
    /// Executes the entire message processing pipeline in an exception handler, tracking the number of failed delivery attempts.
    /// Forwards the message to the error queue when the max number of delivery attempts has been exceeded.
    /// </summary>
    public async Task Process(IncomingStepContext context, Func <Task> next)
    {
        var transportMessage   = context.Load <TransportMessage>() ?? throw new RebusApplicationException("Could not find a transport message in the current incoming step context");
        var transactionContext = context.Load <ITransactionContext>() ?? throw new RebusApplicationException("Could not find a transaction context in the current incoming step context");

        var messageId = transportMessage.Headers.GetValueOrNull(Headers.MessageId);

        if (string.IsNullOrWhiteSpace(messageId))
        {
            await MoveMessageToErrorQueue(context, transactionContext,
                                          new RebusApplicationException($"Received message with empty or absent '{Headers.MessageId}' header! All messages must be" +
                                                                        " supplied with an ID . If no ID is present, the message cannot be tracked" +
                                                                        " between delivery attempts, and other stuff would also be much harder to" +
                                                                        " do - therefore, it is a requirement that messages be supplied with an ID."));

            return;
        }

        if (_errorTracker.HasFailedTooManyTimes(messageId))
        {
            // if we don't have 2nd level retries, just get the message out of the way
            if (!_simpleRetryStrategySettings.SecondLevelRetriesEnabled)
            {
                var aggregateException = GetAggregateException(messageId);
                await MoveMessageToErrorQueue(context, transactionContext, aggregateException);

                _errorTracker.CleanUp(messageId);
                return;
            }

            // change the identifier to track by to perform this 2nd level of delivery attempts
            var secondLevelMessageId = GetSecondLevelMessageId(messageId);

            if (_errorTracker.HasFailedTooManyTimes(secondLevelMessageId))
            {
                var aggregateException = GetAggregateException(messageId, secondLevelMessageId);
                await MoveMessageToErrorQueue(context, transactionContext, aggregateException);

                _errorTracker.CleanUp(messageId);
                _errorTracker.CleanUp(secondLevelMessageId);
                return;
            }

            context.Save(DispatchAsFailedMessageKey, true);

            await DispatchWithTrackerIdentifier(next, secondLevelMessageId, transactionContext, messageId, secondLevelMessageId);

            return;
        }

        await DispatchWithTrackerIdentifier(next, messageId, transactionContext, messageId);
    }
        public async Task CanRestoreIdentity()
        {
            var step     = new RestorePrincipalFromIncomingMessage(new DummySerializer());
            var instance = new Message(new Dictionary <string, string>(), new object());
            var context  = new IncomingStepContext(new TransportMessage(new Dictionary <string, string>(), new byte[0]), new FakeTransactionContext());

            instance.Headers[CapturePrincipalInOutgoingMessage.PrincipalCaptureKey] = "Larry";
            context.Save(instance);
            await step.Process(context, async() =>
            {
                Assert.AreEqual(ClaimsPrincipal.Current.Identity.Name, "Larry");
            });
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Looks up handlers for the incoming message and saves the handlers (without invoking them) to the context as a <see cref="HandlerInvokers"/>
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transactionContext = context.Load <ITransactionContext>();
            var message            = context.Load <Message>();
            var body           = message.Body;
            var messageType    = body.GetType();
            var methodToInvoke = _dispatchMethods
                                 .GetOrAdd(messageType, type => GetDispatchMethod(messageType));

            var handlerInvokers = await((Task <HandlerInvokers>)methodToInvoke.Invoke(this, new[] { body, transactionContext, message }));

            context.Save(handlerInvokers);

            await next();
        }
Ejemplo n.º 19
0
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transactionContext = context.Load <ITransactionContext>(SafeRebusContextTags.TransactionContextTag);
            var scope            = transactionContext.GetOrAdd(SafeRebusContextTags.ScopeContextTag, () => ServiceProvider.CreateScope());
            var adapter          = scope.ServiceProvider.GetService <ISafeStandardAdapter>();
            var transportMessage = context.Load <TransportMessage>();

            if (adapter.IsUsableOnIncoming(transportMessage))
            {
                transportMessage = adapter.ConvertIncomingTransportMessage(transportMessage);
                context.Save(transportMessage);
            }

            await next();
        }
Ejemplo n.º 20
0
        static IncomingStepContext GetIncomingStepContext(int number)
        {
            const string messageId = "some-id";
            var          headers   = new Dictionary <string, string>
            {
                { Headers.MessageId, messageId },
                { "number", (number % 20).ToString() }
            };

            var transportMessage   = new TransportMessage(headers, new byte[0]);
            var transactionContext = new TransactionContext();
            var context            = new IncomingStepContext(transportMessage, transactionContext);
            var message            = new Message(headers, new object());

            context.Save(message);

            var handlerInvokers = new HandlerInvokers(message, new[]
            {
                new HandlerInvoker <object>(messageId, async() => {}, new WhateverSaga(), transactionContext),
            });

            context.Save(handlerInvokers);
            return(context);
        }
Ejemplo n.º 21
0
    public Task Process(IncomingStepContext context, Func <Task> next)
    {
        var message         = context.Load <Message>();
        var handlerInvokers = context.Load <HandlerInvokers>().ToList();

        if (handlerInvokers.All(x => x.Handler is IRebusDistributedEventHandlerAdapter))
        {
            handlerInvokers = new List <HandlerInvoker> {
                handlerInvokers.Last()
            };
            context.Save(new HandlerInvokers(message, handlerInvokers));
        }

        return(next());
    }
Ejemplo n.º 22
0
        public Task Process(IncomingStepContext context, Func <Task> next)
        {
            var currentHandlerInvokers = context.Load <HandlerInvokers>();

            var message     = currentHandlerInvokers.Message;
            var messageType = message.GetMessageType();

            var wrappedHandlerInvokers = currentHandlerInvokers
                                         .Select(invoker => new HandlerInvokerWrapper(invoker, messageType));

            var updatedHandlerInvokers = new HandlerInvokers(message, wrappedHandlerInvokers);

            context.Save(updatedHandlerInvokers);

            return(next());
        }
        /// <summary>
        /// Descrypts the incoming <see cref="TransportMessage"/> if it has the <see cref="EncryptionHeaders.ContentEncryption"/> header
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transportMessage = context.Load <TransportMessage>();

            if (transportMessage.Headers.ContainsKey(EncryptionHeaders.ContentEncryption))
            {
                var headers            = transportMessage.Headers.Clone();
                var encryptedBodyBytes = transportMessage.Body;

                var iv        = GetIv(headers);
                var bodyBytes = _encryptor.Decrypt(new EncryptedData(encryptedBodyBytes, iv));

                context.Save(new TransportMessage(headers, bodyBytes));
            }

            await next();
        }
Ejemplo n.º 24
0
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            if (context.Load <bool>(SimpleRetryStrategyStep.DispatchAsFailedMessageKey))
            {
                var originalMessage = context.Load <Message>();

                var messageId            = originalMessage.GetMessageId();
                var fullErrorDescription = _errorTracker.GetFullErrorDescription(messageId) ?? "(not available in the error tracker!)";
                var headers     = originalMessage.Headers;
                var body        = originalMessage.Body;
                var wrappedBody = WrapInFailed(headers, body, fullErrorDescription);

                context.Save(new Message(headers, wrappedBody));
            }

            await next();
        }
        /// <summary>
        /// Descrypts the incoming <see cref="TransportMessage"/> if it has the <see cref="EncryptionHeaders.ContentEncryption"/> header
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transportMessage = context.Load <TransportMessage>();

            if (transportMessage.Headers.TryGetValue(EncryptionHeaders.ContentEncryption, out var contentEncryptionValue) &&
                contentEncryptionValue == _encryptor.ContentEncryptionValue)
            {
                var headers            = transportMessage.Headers.Clone();
                var encryptedBodyBytes = transportMessage.Body;

                var iv        = GetIv(headers);
                var bodyBytes = _encryptor.Decrypt(new EncryptedData(encryptedBodyBytes, iv));

                context.Save(new TransportMessage(headers, bodyBytes));
            }

            await next().ConfigureAwait(false);
        }
        public CorrelateIncomingMessageStepTests()
        {
            _asyncCorrelationManagerMock = new Mock <IAsyncCorrelationManager>();

            var txItems = new ConcurrentDictionary <string, object>();
            var transactionContextMock = new Mock <ITransactionContext>();

            transactionContextMock
            .Setup(m => m.Items)
            .Returns(txItems);

            _messageHeaders = new Dictionary <string, string>();
            var transportMessage = new TransportMessage(_messageHeaders, Array.Empty <byte>());

            _stepContext = new IncomingStepContext(transportMessage, transactionContextMock.Object);
            _stepContext.Save(new Message(_messageHeaders, new { }));

            _next = () => Task.CompletedTask;

            _sut = new CorrelateIncomingMessageStep(_asyncCorrelationManagerMock.Object, new NullLoggerFactory());
        }
        public ValidationFailedStrategyTests()
        {
            LoggerFactory = new XunitRebusLoggerFactory();
            Logger        = LoggerFactory.GetLogger <ValidationFailedStrategyTests>();

            _tx = new RebusTransactionScope();

            var headers = new Dictionary <string, string>
            {
                { Headers.MessageId, Guid.NewGuid().ToString() },
                { Headers.Type, typeof(TestMessage).GetSimpleAssemblyQualifiedName() }
            };
            var transportMessage = new TransportMessage(headers, new byte[0]);

            StepContext = new IncomingStepContext(transportMessage, _tx.TransactionContext);
            StepContext.Save(Message = new Message(headers, new TestMessage()));

            ValidatorMock = new Mock <IValidator>();
            ValidatorMock
            .Setup(m => m.ValidateAsync(It.IsAny <object>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(ValidationResult);
        }
Ejemplo n.º 28
0
        private async Task _handleError(IncomingStepContext context, Func <Task> next, string handledMessageId)
        {
            var transportMessage     = context.Load <TransportMessage>() ?? throw new RebusApplicationException("Could not find a transport message in the current incoming step context");
            var transactionContext   = context.Load <ITransactionContext>();
            var messageId            = transportMessage.Headers.GetValueOrNull(Headers.MessageId);
            var secondLevelMessageId = GetSecondLevelMessageId(messageId);

            if (!_errorTracker.HasFailedTooManyTimes(handledMessageId)) // let's try again
            {
                transactionContext.Abort();
                return;
            }
            else if (messageId == handledMessageId && _arkRetryStrategySettings.SecondLevelRetriesEnabled && !_errorTracker.HasFailedTooManyTimes(secondLevelMessageId))
            {
                context.Save(DispatchAsFailedMessageKey, true);
                await _handle(context, next, secondLevelMessageId, transactionContext, messageId, secondLevelMessageId);

                return;
            }

            await _handlePoisonMessage(context, transactionContext, messageId, secondLevelMessageId);
        }