NServiceBus icon indicating copy to clipboard operation
NServiceBus copied to clipboard

Premature ITransportAddressResolver access corrupts service

Open timbussmann opened this issue 1 year ago • 1 comments

Describe the bug

Description

When using the generic host, it is possible to resolve ITransportAddressResolver before the endpoint has been started. A potential scenario is a hosted service that is trying to use the TransactionalSession (which internally uses the ITransportAddressResolver).

Resolving the ITransportAddressResolver will produce an instance which uses the transportSeam.TransportInfrastructure property which is still null, causing it to throw an NRE once an attempt to translate a transport address is made. Since the service is registered as a singleton, all users of the singleton will receive the invalid instance and thus run into an NRE on any call to the address resolver.

Expected behavior

The endpoint should be able to start successfully.

Additionally, it would be nicer if the code that tries to access the ITransportAddressResolver prematurely will receive an exception, warning about the startup order rather than a corrupted instance which will throw NRE's on usage.

Actual behavior

The endpoint fails to start with an exception:

System.NullReferenceException: Object reference not set to an instance of an object.
   at NServiceBus.TransportAddressResolver.ToTransportAddress(QueueAddress queueAddress) in /_/src/NServiceBus.Core/Transports/TransportAddressResolver.cs:line 14
   at NServiceBus.TransactionalSession.TransactionalSession.<>c.<Setup>b__1_2(IServiceProvider sp) in /_/src/NServiceBus.TransactionalSession/TransactionalSession.cs:line 74
   at NServiceBus.Pipeline.PipelineSettings.<>c__DisplayClass11_0`1.<Register>b__0(IServiceProvider b) in /_/src/NServiceBus.Core/Pipeline/PipelineSettings.cs:line 180
   at NServiceBus.Pipeline.RegisterStep.CreateBehavior(IServiceProvider defaultBuilder) in /_/src/NServiceBus.Core/Pipeline/RegisterStep.cs:line 131
   at NServiceBus.Pipeline`1.<>c__DisplayClass0_0.<.ctor>b__0(RegisterStep r) in /_/src/NServiceBus.Core/Pipeline/Pipeline.cs:line 27
   at System.Linq.Enumerable.SelectListIterator`2.Fill(ReadOnlySpan`1 source, Span`1 destination, Func`2 func)
   at System.Linq.Enumerable.SelectListIterator`2.ToArray()
   at NServiceBus.Pipeline`1..ctor(IServiceProvider builder, PipelineModifications pipelineModifications) in /_/src/NServiceBus.Core/Pipeline/Pipeline.cs:line 26
   at NServiceBus.PipelineComponent.CreatePipeline[T](IServiceProvider builder) in /_/src/NServiceBus.Core/Pipeline/PipelineComponent.cs:line 32
   at NServiceBus.ReceiveComponent.Initialize(IServiceProvider builder, RecoverabilityComponent recoverabilityComponent, MessageOperations messageOperations, PipelineComponent pipelineComponent, IPipelineCache pipelineCache, TransportInfrastructure transportInfrastructure, ConsecutiveFailuresConfiguration consecutiveFailuresConfiguration, CancellationToken cancellationToken) in /_/src/NServiceBus.Core/Receiving/ReceiveComponent.cs:line 157
   at NServiceBus.StartableEndpoint.Setup(CancellationToken cancellationToken) in /_/src/NServiceBus.Core/StartableEndpoint.cs:line 50
   at NServiceBus.ExternallyManagedContainerHost.Start(IServiceProvider externalBuilder, CancellationToken cancellationToken) in /_/src/NServiceBus.Core/Hosting/ExternallyManagedContainerHost.cs:line 41
   at NServiceBus.Extensions.Hosting.NServiceBusHostedService.StartAsync(CancellationToken cancellationToken) in /_/src/NServiceBus.Extensions.Hosting/NServiceBusHostedService.cs:line 30
   at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
   at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)

Versions

Please list the version of the relevant packages or applications in which the bug exists.

Core v8 + TransactionalSession for SQLP

Steps to reproduce

  1. Create a hosted service which accesses ITransportAddressResolver
  2. Register the hosted service before calling UseNServiceBus on the generic host setup
  3. Start the host

Relevant log output

No response

Additional Information

Workarounds

Possible solutions

Additional information

timbussmann avatar Mar 05 '24 12:03 timbussmann

Thanks, we're looking in to it. We need to validate a few things before accepting the proposed fix too.

WilliamBZA avatar Mar 06 '24 12:03 WilliamBZA