Particular / NServiceBus.RabbitMQ

RabbitMQ transport for NServiceBus
https://docs.particular.net/nservicebus/rabbitmq/
Other
88 stars 59 forks source link

nsbVersion can't be computed in single file deployments #1255

Open eb2tech opened 1 year ago

eb2tech commented 1 year ago

Describe the bug

Description

When an executable built as a single file deployment tries to start an endpoint, computation of nsbVersion in ConnectionFactory.cs, line 92 fails with a System.ArgumentException. The property System.Reflection.Assembly.Location is empty for single file deployments because there is no file location.

Expected behavior

nsbVersion (and rabbitMQVersion) are computed successfully and client properties are set.

Actual behavior

nsbVersion is not computed and fails with an ArgumentException.

Versions

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

Steps to reproduce

Take any sample application and create a single file deployment using dotnet publish. Then run the application.

Relevant log output

[10:33:49 ERR] Failed to start...
System.ArgumentException: The path is empty. (Parameter 'path')
   at System.IO.Path.GetFullPath(String path)
   at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName)
   at NServiceBus.Transport.RabbitMQ.ConnectionFactory.SetClientProperties(String endpointName, String userName) in /_/src/NServiceBus.Transport.RabbitMQ/Connection/ConnectionFactory.cs:line 92
   at NServiceBus.Transport.RabbitMQ.ConnectionFactory..ctor(String endpointName, ConnectionConfiguration connectionConfiguration, X509Certificate2Collection clientCertificateCollection, Boolean disableRemoteCertificateValidation, Boolean useExternalAuthMechanism, TimeSpan heartbeatInterval, TimeSpan networkRecoveryInterval, List`1 additionalClusterNodes) in /_/src/NServiceBus.Transport.RabbitMQ/Connection/ConnectionFactory.cs:line 52
   at NServiceBus.RabbitMQTransport.Initialize(HostSettings hostSettings, ReceiveSettings[] receivers, String[] sendingAddresses, CancellationToken cancellationToken) in /_/src/NServiceBus.Transport.RabbitMQ/RabbitMQTransport.cs:line 167
   at NServiceBus.TransportSeam.CreateTransportInfrastructure(CancellationToken cancellationToken) in /_/src/NServiceBus.Core/Transports/TransportSeam.cs:line 36
   at NServiceBus.StartableEndpoint.Start(CancellationToken cancellationToken) in /_/src/NServiceBus.Core/StartableEndpoint.cs:line 35
   at NServiceBus.HostingComponent.Start(IStartableEndpoint startableEndpoint, CancellationToken cancellationToken) in /_/src/NServiceBus.Core/Hosting/HostingComponent.cs:line 84
   at NServiceBus.Endpoint.Start(EndpointConfiguration configuration, CancellationToken cancellationToken) in /_/src/NServiceBus.Core/Endpoint.cs:line 34
   at Foundation.Coding.Tasks.TaskExtensions.Inline[TResult](Task`1 task)
   at Submission#0.<<Initialize>>b__0_0(IComponentContext x) in C:\dev\repos\Estream\Source\csi.scripts\Setup.Common.csx:line 137

Additional Information

Workarounds

Possible solutions

Obtain version information from System.Reflection.Assembly.FullName. In fact, since the value seems to be used as an opaque string, simply use the assembly's full name or typeof(Endpoint).AssemblyQualifiedName. A System.Type's AssemblyQualifiedName is as precise as one can get, especially if the name is strong.

Additional information

awright18 commented 1 year ago

@eb2tech Thanks for your feedback regarding single-file deployments using NServiceBus.RabbitMQ. As you have discovered the Assembly.Location API is not currently compatible with single file application deployments.

DavidBoike commented 1 year ago

We don't officially support single-file deployments for NServiceBus endpoints at the moment. It's kind of a Your Mileage May Vary sort of situation at the moment–if we by luck didn't use any APIs that won't work in a single-file deployment, then it will work great!

But we don't explicitly test for that. And since we don't test for it, even if it worked today, it would be really easy for it to regress tomorrow.

Running our entire test suite as a single-file deployment probably isn't going to be workable, so what we would probably need is a Roslyn analyzer that detected usages of APIs like Assembly.Location that are going to cause you to have a bad time. Or such analyzers may already exist but we haven't enabled them yet in our global .editorconfig files.

Either way, properly supporting single-file deployments is a larger effort than changing this one problematic API usage.