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; } } }
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()); }
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)); }
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); }
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); }
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(); }
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(); }
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); }
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()); }
/// <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)); }
/// <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); }
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(); }
/// <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"); }); }
/// <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(); }
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(); }
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); }
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()); }
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(); }
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); }
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); }