private async Task SendMessageToDeadLetterQueueAsync(MessageExecutionContext messageExecutionContext, int retrycount) { IntegrationEvent <JObject> integrationEvent = null; if (!string.IsNullOrEmpty(messageExecutionContext.SerializedMessage)) { integrationEvent = JsonConvert.DeserializeObject <IntegrationEvent <JObject> >(messageExecutionContext.SerializedMessage); } var deadLetterEventDescriptor = new DeadLetterEventDescriptor <JObject> { CountOfAttempts = retrycount, LastAttemptError = messageExecutionContext.Exception.ToString(), Original = integrationEvent }; messageExecutionContext.DeadLetterIntegrationEvent = new IntegrationEvent <DeadLetterEventDescriptor <JObject> > { EventType = _modelNamingConventionController.GetDeadLetterQueueMessageEventType( integrationEvent?.EventType), Content = deadLetterEventDescriptor }; await _failedExecutionHandler(messageExecutionContext); }
public async void HandleErrorAsync_ExceptionThatShouldBeCatchedANDLastAttempt_MessageShouldBeSentToAppropriateDeadLetterQueue(bool explicitAcknowledgments, bool storedeadletter) { //prepare MessageProperties messageProperties = new MessageProperties(); messageProperties.Headers = new Dictionary <string, object>(); messageProperties.Headers["retrycount"] = _maxRetry; BookingCreated bookingCreated = new BookingCreated { BookingName = "test" }; string bookingCreatedEventType = "bookingCreatedEventType"; IntegrationEvent <BookingCreated> integrationEvent = new IntegrationEvent <BookingCreated>(bookingCreated, bookingCreatedEventType); var message = JsonConvert.SerializeObject(integrationEvent); var body = Encoding.UTF8.GetBytes(message); Exception exception = new IOException("IOException"); ExecutionHandlingStrategy executionHandlingStrategy = new ExecutionHandlingStrategy(_subscriberName, _easyNetQPublisher, _maxRetry, _modelNamingConventionController.Object, explicitAcknowledgments, _publisher.Object, storedeadletter); _mockBus.Setup(x => x.ExchangeDeclareAsync(_exchangeName, ExchangeType.Topic, false, true, false, false, null, false)) .Returns((string exchangename, string exchanegType, bool passive, bool durable, bool autoDelete, bool internalflag, string alternateExchange, bool delayed) => { return(Task.FromResult(_mockExchange.Object)); }); _modelNamingConventionController.Setup(x => x.GetDeadLetterQueueMessageEventType(bookingCreatedEventType)) .Returns((string eventType) => string.Concat("deadletter.", eventType)); _modelNamingConventionController.Setup(x => x.GetDeadLetterQueueRoutingKey(_subscriberName)) .Returns((string subscriberName) => string.Concat("deadletter.", subscriberName)); //Main flow string actualRouting = string.Empty; MessageProperties actualProperties = null; byte[] actualMsg = null; IExchange actualExchange = null; _mockBus.Setup(x => x.PublishAsync(It.IsAny <IExchange>(), It.IsAny <string>(), false, It.IsAny <MessageProperties>(), It.IsAny <byte[]>())) .Returns((IExchange exchange, string routing, bool mandatory, MessageProperties properties, byte[] msg) => { return(Task.FromResult(true)); }) .Callback <IExchange, string, bool, MessageProperties, byte[]>( (exchange, routing, mandatory, properties, msg) => { actualExchange = exchange; actualRouting = routing; actualProperties = properties; actualMsg = msg; }); //END Main flow //Tracking flow IntegrationEvent <DeadLetterEventDescriptor <JObject> > actualTrackingMessage = null; string actualTrackingMessageRouting = string.Empty; bool actualPersistantMode = false; _publisher.Setup(x => x.PublishEventAsync(It.IsAny <IntegrationEvent <DeadLetterEventDescriptor <JObject> > >(), It.IsAny <string>(), true)) .Returns(Task.FromResult(true)) .Callback <IntegrationEvent <DeadLetterEventDescriptor <JObject> >, string, bool>( (trackingMessage, routing, persistantMode) => { actualTrackingMessage = trackingMessage; actualTrackingMessageRouting = routing; actualPersistantMode = persistantMode; }); //END Tracking flow //act Mock <ISubscription> mockedSubscription = new Mock <ISubscription>(); MessageExecutionContext messageExecutionContext = new MessageExecutionContext(body, messageProperties, null) { Exception = exception, SerializedMessage = message, Subscription = mockedSubscription.Object, IntergrationEventParsingResult = null, DeadLetterIntegrationEvent = null }; await executionHandlingStrategy.HandleErrorAsync(messageExecutionContext); //check var expectedDeadLetterEventDescriptor = new DeadLetterEventDescriptor <JObject> { CountOfAttempts = _maxRetry, LastAttemptError = exception.ToString(), Original = JsonConvert.DeserializeObject <IntegrationEvent <JObject> >(message) }; var expectedDeadletterqueueevent = new IntegrationEvent <DeadLetterEventDescriptor <JObject> > { CorrelationId = integrationEvent.CorrelationId, EventType = string.Concat("deadletter.", bookingCreatedEventType), Content = expectedDeadLetterEventDescriptor }; //Check publishing dead letter message if (storedeadletter) { var actuaDeadLetterQueuelSerializedMessage = Encoding.UTF8.GetString(actualMsg); IntegrationEvent <DeadLetterEventDescriptor <JObject> > actualDeadLetterQueueIntegrationEvent = JsonConvert.DeserializeObject <IntegrationEvent <DeadLetterEventDescriptor <JObject> > >(actuaDeadLetterQueuelSerializedMessage); actualDeadLetterQueueIntegrationEvent.CorrelationId.Should().Be(expectedDeadletterqueueevent.CorrelationId); actualDeadLetterQueueIntegrationEvent.Content.ShouldBeEquivalentTo(expectedDeadletterqueueevent.Content); actualDeadLetterQueueIntegrationEvent.EventType.Should() .Be(expectedDeadletterqueueevent.EventType); actualRouting.Should().Be(string.Concat("deadletter.", _subscriberName)); actualExchange.Should().Be(_mockExchange.Object); actualProperties.DeliveryMode.Should().Be(2);//persistant delivery mode } else { _mockBus.Verify(v => v.PublishAsync(It.IsAny <IExchange>(), It.IsAny <string>(), false, It.IsAny <MessageProperties>(), It.IsAny <byte[]>()), Times.Never); } //Check Subsciption notification mockedSubscription.Verify(s => s.NotifyAboutDeadLetterAsync(messageExecutionContext.SerializedMessage, messageExecutionContext.Exception), Times.Once); mockedSubscription.Verify(s => s.InvokeAsync(It.IsAny <string>()), Times.Never); //Check Tracking flow if (explicitAcknowledgments == false) { //check, that No deadletter message for tracking is sent. _publisher.Verify(v => v.PublishEventAsync(It.IsAny <IntegrationEvent <DeadLetterEventDescriptor <JObject> > >(), It.IsAny <string>(), It.IsAny <bool>()), Times.Never); } else { //check, that deadltter message for tracking is equal to the one sent to the deadletter queue. Routing key must be the same _publisher.Verify(v => v.PublishEventAsync(It.IsAny <IntegrationEvent <DeadLetterEventDescriptor <JObject> > >(), It.IsAny <string>(), It.IsAny <bool>()), Times.Once); actualTrackingMessageRouting.Should().Be(string.Concat("deadletter.", _subscriberName)); actualPersistantMode.Should().BeTrue(); actualTrackingMessage.CorrelationId.Should().Be(expectedDeadletterqueueevent.CorrelationId); actualTrackingMessage.Content.ShouldBeEquivalentTo(expectedDeadletterqueueevent.Content); actualTrackingMessage.EventType.Should() .Be(expectedDeadletterqueueevent.EventType); } }