rebus-org / Rebus.Autofac

:bus: Autofac container adapter for Rebus
https://mookid.dk/category/rebus
Other
12 stars 11 forks source link

NullReference exception if message received before initialization finished #14

Closed Radiofisik closed 4 years ago

Radiofisik commented 5 years ago

I use the lib with rabbitMq. Config is something like

   builder.RegisterRebus((configurer, context) => configurer
                    .Logging(l => l.Serilog())
                    .Transport(t => t.UseRabbitMq("amqp://docker", "testappqueue"))
                .Options(o => {
                    o.SetNumberOfWorkers(1);
                    o.SetMaxParallelism(30);
                }));

If a message was received by rabbitMq while the application was not running it tries to process the message before initialization finished. The reason is _container is null in the code below

ILifetimeScope CreateLifetimeScope()
            {
                var scope = _container.BeginLifetimeScope();
                transactionContext.OnDisposed(() => scope.Dispose());
                return scope;
            }
mookid8000 commented 5 years ago

Hi @Radiofisik , I've been trying to reproduce this issue without success (as in: I could NOT reproduce it, things seemed to work as they should).

The code I used is here: DoesNotTryToHandleMessagesBeforeTheBusIsProperlyStarted.cs

It uses the in-mem transport, which is much faster than RabbitMQ, but that didn't cause any exceptions when starting.

I also tried changing the transport to RabbitMQ, but that didn't change anything either.

Could you maybe help me reproduce the issue?

Radiofisik commented 5 years ago

@mookid8000 , It seems that it is not stable, I also cannot reproduce it with the unit test. But I can reproduce it with a simple hello world like .net core application. screen Steps to reproduce:

mookid8000 commented 5 years ago

I tried your program, and then I got the error.... this is so weird.

I'll need some more time to debug it. I'll be back 😐

mookid8000 commented 5 years ago

Hi again @Radiofisik , sorry for the long delay 🙄 I've played around a little bit – could you update to Rebus.Autofac 6.0.0-b08 and see if it fixes your problem?

Radiofisik commented 5 years ago

Hi, @mookid8000, I tried to update to Rebus.Autofac 6.0.0-b08 and it does not solve the problem. The same exception was thrown...

08:27:01 WRN] Unhandled exception 1 while handling message with ID f3a34e5b-7b09-4398-8924-1cff4d00d513
Rebus.Exceptions.RebusApplicationException: Could not 'GetOrAdd' item with key 'current-autofac-lifetime-scope' as type Autofac.ILifetimeScope ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Rebus.Autofac.AutofacHandlerActivator.<>c__DisplayClass5_0`1.<GetHandlers>g__CreateLifetimeScope|0()
   at Rebus.Transport.TransactionContextExtensions.<>c__DisplayClass2_0`1.<GetOrAdd>b__0(String id) in C:\projects-rebus\Rebus\Rebus\Transport\TransactionContextExtensions.cs:line 61
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Rebus.Transport.TransactionContextExtensions.GetOrAdd[TItem](ITransactionContext context, String key, Func`1 newItemFactory)
   --- End of inner exception stack trace ---
   at Rebus.Transport.TransactionContextExtensions.GetOrAdd[TItem](ITransactionContext context, String key, Func`1 newItemFactory) in C:\projects-rebus\Rebus\Rebus\Transport\TransactionContextExtensions.cs:line 65
   at Rebus.Autofac.AutofacHandlerActivator.GetHandlers[TMessage](TMessage message, ITransactionContext transactionContext)
   at Rebus.Handlers.InternalHandlersContributor.GetHandlers[TMessage](TMessage message, ITransactionContext transactionContext)
   at Rebus.Pipeline.Receive.ActivateHandlersStep.GetHandlerInvokers[TMessage](TMessage message, ITransactionContext transactionContext, Message logicalMessage)
   at Rebus.Pipeline.Receive.ActivateHandlersStep.Process(IncomingStepContext context, Func`1 next) in C:\projects-rebus\Rebus\Rebus\Pipeline\Receive\ActivateHandlersStep.cs:line 43
   at Rebus.Pipeline.Receive.HandleRoutingSlipsStep.Process(IncomingStepContext context, Func`1 next) in C:\projects-rebus\Rebus\Rebus\Pipeline\Receive\HandleRoutingSlipsStep.cs:line 42
   at Rebus.Pipeline.Receive.DeserializeIncomingMessageStep.Process(IncomingStepContext context, Func`1 next) in C:\projects-rebus\Rebus\Rebus\Pipeline\Receive\DeserializeIncomingMessageStep.cs:line 34
   at Rebus.DataBus.ClaimCheck.HydrateIncomingMessageStep.Process(IncomingStepContext context, Func`1 next) in C:\projects-rebus\Rebus\Rebus\DataBus\ClaimCheck\HydrateIncomingMessageStep.cs:line 51
   at Rebus.Pipeline.Receive.HandleDeferredMessagesStep.Process(IncomingStepContext context, Func`1 next) in C:\projects-rebus\Rebus\Rebus\Pipeline\Receive\HandleDeferredMessagesStep.cs:line 121
   at Rebus.Retry.FailFast.FailFastStep.Process(IncomingStepContext context, Func`1 next) in C:\projects-rebus\Rebus\Rebus\Retry\FailFast\FailFastStep.cs:line 41
   at Rebus.Retry.Simple.SimpleRetryStrategyStep.DispatchWithTrackerIdentifier(Func`1 next, String identifierToTrackMessageBy, ITransactionContext transactionContext, String messageId, String secondLevelMessageId) in C:\projects-rebus\Rebus\Rebus\Retry\Simple\SimpleRetryStrategyStep.cs:line 120
leomenca commented 4 years ago

Hi @Radiofisik, the problem is due to a race condition between the activator and the rebus start.

You are probably resolving IBus in your configuration code (maybe for subscriptions in a autofac buildCallback). This actually leads Rebus to start before the activator could assign the container.

I created a pull request to solve this. I also need to nest my bus instance in a child autofac lifetimescope. So my pull request comes in.

mookid8000 commented 4 years ago

Should be fixed by #16

Thanks again, @leomenca ! 👍