Error registering IErrorHandler with Rebus

0

Error below occurred:

System.InvalidOperationException HResult=0x80131509 Message=A circular dependency was detected for the service of type 'Rebus.Retry.IErrorHandler'. Rebus.Retry.IErrorHandler(Rebus.AzureServiceBus.ErrorMessage.ErrorMessageHandler) -> Rebus.Retry.IErrorHandler Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain.CheckCircularDependency(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider) at RebusSubscriber.<>c__DisplayClass7_0`1.b__5(IResolutionContext c) in C:_Repos\AzureServiceBus\Subscriber\RebusSubscriber.cs:line 45 at Rebus.Injection.Injectionist.ResolutionContext.GetTService

Below registers dependency for IErrorHandler

services.AddTransient<IErrorHandler, ErrorMessageHandler>();

Below is how it resolves ErrorMessageHandler and error above occurred.

Configure.With(Activator)
                .Options(o =>
                {                   
                    o.Decorate<IErrorHandler>(c => 
new ErrorMessageHandler(c.Get<IErrorHandler>()));
                    }



public class ErrorMessageHandler : IErrorHandler
    {
        private readonly IErrorHandler _errorHandler;

        public ErrorMessageHandler(IErrorHandler errorHandler)
        {
            _errorHandler = errorHandler;
        } 

        public async Task HandlePoisonMessage(TransportMessage transportMessage, ITransactionContext transactionContext, Exception exception)
        {
            // keep original behaviour
            await _errorHandler.HandlePoisonMessage(transportMessage, transactionContext, exception);
        }
    }

It seems not using IResolutionContext causes the error.

Is there a solution?

Update

The problem is that IResolutionContext is required to register its own implementation instead of own IoC. It seems the name of IErrorHandler is overused.

My requirement is, given two separate components (Rebus wrapper, and its client), that we need to let client of rebus wrapper to define and use custom error handler, ErrorMessageHandler in this case.

For example, the pseudocode of Rebus wrapper below:

Configure.With(Activator)
                    .Options(o =>
                    {                   

//logic to implement below that allow different message handler somehow
//ErrorMessageHandler is this case.
                        o.Decorate<IErrorHandler>(c => 
           xxxxxxx(c.Get<IErrorHandler>()));
                        }

Pseudocode of Client of the Rebus wrapper:

 //pass ErrorMessageHandler to the Rebus wrapper above.
rebus
asked on Stack Overflow May 31, 2019 by Pingpong • edited Jun 1, 2019 by Pingpong

1 Answer

0

The error comes from the Microsoft Dependency Injection container – it's caused by the fact that your IErrorHandler implementation takes an IErrorHandler in its constructor, which it doesn't seem to like.

This particular pattern is the Decorator pattern, which helps transparently extend the capabilities of existing services. Rebus encourages you to use it to extend its behavior, which you seem to be doing correctly by registering it with configurer.Decorate<IErrorHandler>(...).

The error in this case seems to be that you're registering your ErrorMessageHandler in your IoC container. Rebus doesn't use your IoC container to resolve its own services, it's ONLY used for resolving message handlers.

Your IErrorHandler is not a message handler, it's the abstraction that decides how Rebus deals with messages once they have failed too many times.

Therefore: Don't register it in your IoC container.

answered on Stack Overflow Jun 1, 2019 by mookid8000

User contributions licensed under CC BY-SA 3.0