public void TestRetryWithinOnMessageAdapter() { var config = new ConfigurationBuilder().Build(); var services = new ServiceCollection().BuildServiceProvider(); var context = new GenericApplicationContext(services, config); var connectionFactory = new Mock <Messaging.RabbitMQ.Connection.IConnectionFactory>(); var container = new DirectMessageListenerContainer(); var adapter = new RabbitInboundChannelAdapter(context, container); adapter.OutputChannel = new DirectChannel(context); adapter.RetryTemplate = new PollyRetryTemplate(3, 1, 1, 1); var errors = new QueueChannel(context); var recoveryCallback = new ErrorMessageSendingRecoverer(context, errors); recoveryCallback.ErrorMessageStrategy = new RabbitMessageHeaderErrorMessageStrategy(); adapter.RecoveryCallback = recoveryCallback; var listener = container.MessageListener as IChannelAwareMessageListener; var message = MessageBuilder.WithPayload <byte[]>(Encoding.UTF8.GetBytes("foo")).CopyHeaders(new MessageHeaders()).Build(); listener.OnMessage(message, null); var errorMessage = errors.Receive(0); Assert.NotNull(errorMessage); var payload = errorMessage.Payload as MessagingException; Assert.NotNull(payload); Assert.Contains("Dispatcher has no", payload.Message); var deliveryAttempts = payload.FailedMessage.Headers.Get <AtomicInteger>(IntegrationMessageHeaderAccessor.DELIVERY_ATTEMPT); Assert.NotNull(deliveryAttempts); Assert.Equal(3, deliveryAttempts.Value); var amqpMessage = errorMessage.Headers.Get <IMessage>(RabbitMessageHeaderErrorMessageStrategy.AMQP_RAW_MESSAGE); Assert.NotNull(amqpMessage); Assert.Null(errors.Receive(0)); }
public ErrorInfrastructure(ISubscribableChannel errorChannel, ErrorMessageSendingRecoverer recoverer, IMessageHandler handler) { ErrorChannel = errorChannel; Recoverer = recoverer; Handler = handler; }
protected virtual ErrorInfrastructure RegisterErrorInfrastructure(IConsumerDestination destination, string group, IConsumerOptions consumerOptions, bool polled) { var errorMessageStrategy = GetErrorMessageStrategy(); var errorChannelName = GetErrorsBaseName(destination, group, consumerOptions); ISubscribableChannel errorChannel; var errorChannelObject = _destinationRegistry.Lookup(errorChannelName); if (errorChannelObject != null) { if (!(errorChannelObject is ISubscribableChannel)) { throw new ArgumentException("Error channel '" + errorChannelName + "' must be a ISubscribableChannel"); } errorChannel = (ISubscribableChannel)errorChannelObject; } else { errorChannel = new BinderErrorChannel(ServiceProvider, errorChannelName); _destinationRegistry.Register(errorChannelName, errorChannel); } ErrorMessageSendingRecoverer recoverer; if (errorMessageStrategy == null) { recoverer = new ErrorMessageSendingRecoverer(ServiceProvider, errorChannel); } else { recoverer = new ErrorMessageSendingRecoverer(ServiceProvider, errorChannel, errorMessageStrategy); } var recovererBeanName = GetErrorRecovererName(destination, group, consumerOptions); _destinationRegistry.Register(recovererBeanName, recoverer); IMessageHandler handler; if (polled) { handler = GetPolledConsumerErrorMessageHandler(destination, group, consumerOptions); } else { handler = GetErrorMessageHandler(destination, group, consumerOptions); } var defaultErrorChannel = (IMessageChannel)_destinationRegistry.Lookup(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME); if (handler == null && errorChannel is ILastSubscriberAwareChannel) { handler = GetDefaultErrorMessageHandler((ILastSubscriberAwareChannel)errorChannel, defaultErrorChannel != null); } var errorMessageHandlerName = GetErrorMessageHandlerName(destination, group, consumerOptions); if (handler != null) { if (IsSubscribable(errorChannel)) { var errorHandler = handler; _destinationRegistry.Register(errorMessageHandlerName, errorHandler); errorChannel.Subscribe(handler); } else { // this.logger.warn("The provided errorChannel '" + errorChannelName // + "' is an instance of DirectChannel, " // + "so no more subscribers could be added which may affect DLQ processing. " // + "Resolution: Configure your own errorChannel as " // + "an instance of PublishSubscribeChannel"); } } if (defaultErrorChannel != null) { if (IsSubscribable(errorChannel)) { var errorBridge = new BridgeHandler(ServiceProvider) { OutputChannel = defaultErrorChannel }; errorChannel.Subscribe(errorBridge); var errorBridgeHandlerName = GetErrorBridgeName(destination, group, consumerOptions); _destinationRegistry.Register(errorBridgeHandlerName, errorBridge); } else { // this.logger.warn("The provided errorChannel '" + errorChannelName // + "' is an instance of DirectChannel, " // + "so no more subscribers could be added and no error messages will be sent to global error channel. " // + "Resolution: Configure your own errorChannel as " // + "an instance of PublishSubscribeChannel"); } } return(new ErrorInfrastructure(errorChannel, recoverer, handler)); }
protected virtual ErrorInfrastructure RegisterErrorInfrastructure(IConsumerDestination destination, string group, IConsumerOptions consumerOptions, bool polled, ILogger logger) { var errorMessageStrategy = GetErrorMessageStrategy(); var errorChannelName = GetErrorsBaseName(destination, group, consumerOptions); var errorChannel = GetErrorChannel(logger, errorChannelName); var recoverer = new ErrorMessageSendingRecoverer(ApplicationContext, errorChannel, errorMessageStrategy); var recovererBeanName = GetErrorRecovererName(destination, group, consumerOptions); ApplicationContext.Register(recovererBeanName, recoverer); IMessageHandler handler; if (polled) { handler = GetPolledConsumerErrorMessageHandler(destination, group, consumerOptions); } else { handler = GetErrorMessageHandler(destination, group, consumerOptions); } var defaultErrorChannel = ApplicationContext.GetService <IMessageChannel>(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME); if (handler == null && errorChannel is ILastSubscriberAwareChannel channel) { handler = GetDefaultErrorMessageHandler(channel, defaultErrorChannel != null); } var errorMessageHandlerName = GetErrorMessageHandlerName(destination, group, consumerOptions); if (handler != null) { handler.ServiceName = errorMessageHandlerName; if (IsSubscribable(errorChannel)) { var errorHandler = handler; ApplicationContext.Register(errorMessageHandlerName, errorHandler); errorChannel.Subscribe(handler); } else { _logger?.LogWarning("The provided errorChannel '" + errorChannelName + "' is an instance of DirectChannel, " + "so no more subscribers could be added which may affect DLQ processing. " + "Resolution: Configure your own errorChannel as " + "an instance of PublishSubscribeChannel"); } } if (defaultErrorChannel != null) { if (IsSubscribable(errorChannel)) { var errorBridge = new BridgeHandler(ApplicationContext) { OutputChannel = defaultErrorChannel }; errorChannel.Subscribe(errorBridge); var errorBridgeHandlerName = GetErrorBridgeName(destination, group, consumerOptions); errorBridge.ServiceName = errorBridgeHandlerName; ApplicationContext.Register(errorBridgeHandlerName, errorBridge); } else { _logger?.LogWarning("The provided errorChannel '" + errorChannelName + "' is an instance of DirectChannel, " + "so no more subscribers could be added and no error messages will be sent to global error channel. " + "Resolution: Configure your own errorChannel as " + "an instance of PublishSubscribeChannel"); } } return(new ErrorInfrastructure(errorChannel, recoverer, handler)); }