Exemplo n.º 1
0
        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);
            }
        }