Closed andrejt closed 3 years ago
We are experiencing this specific issue and getting a InitialConnectionException
.
If the connection to RabbitMQ cannot be establish the entire Application fails because the Depedency cannot be injected.
RabbitMQ.Client.Core.DependencyInjection.Exceptions.InitialConnectionException
HResult=0x80131500
Message=Could not establish an initial connection in 5 retries
Source=RabbitMQ.Client.Core.DependencyInjection
StackTrace:
at RabbitMQ.Client.Core.DependencyInjection.Services.RabbitMqConnectionFactory.TryToCreateConnection(Func`1 connectionFunction, Int32 numberOfRetries, Int32 timeoutMilliseconds) in C:\Repos\RabbitMQ.Client.Core.DependencyInjection\src\RabbitMQ.Client.Core.DependencyInjection\Services\RabbitMqConnectionFactory.cs:line 139
at RabbitMQ.Client.Core.DependencyInjection.Services.RabbitMqConnectionFactory.CreateConnectionWithTcpEndpoints(RabbitMqClientOptions options, ConnectionFactory factory) in C:\Repos\RabbitMQ.Client.Core.DependencyInjection\src\RabbitMQ.Client.Core.DependencyInjection\Services\RabbitMqConnectionFactory.cs:line 86
at RabbitMQ.Client.Core.DependencyInjection.Services.RabbitMqConnectionFactory.CreateRabbitMqConnection(RabbitMqClientOptions options) in C:\Repos\RabbitMQ.Client.Core.DependencyInjection\src\RabbitMQ.Client.Core.DependencyInjection\Services\RabbitMqConnectionFactory.cs:line 45
at RabbitMQ.Client.Core.DependencyInjection.Services.QueueService.ConfigureConnectionInfrastructure(RabbitMqConnectionOptionsContainer optionsContainer) in C:\Repos\RabbitMQ.Client.Core.DependencyInjection\src\RabbitMQ.Client.Core.DependencyInjection\Services\QueueService.cs:line 338
at RabbitMQ.Client.Core.DependencyInjection.Services.QueueService..ctor(Guid guid, IRabbitMqConnectionFactory rabbitMqConnectionFactory, IEnumerable`1 connectionOptionsContainers, IMessageHandlingPipelineExecutingService messageHandlingPipelineExecutingService, IEnumerable`1 exchanges, ILogger`1 logger) in C:\Repos\RabbitMQ.Client.Core.DependencyInjection\src\RabbitMQ.Client.Core.DependencyInjection\Services\QueueService.cs:line 61
at RabbitMQ.Client.Core.DependencyInjection.RabbitMqClientDependencyInjectionExtensions.<>c__DisplayClass17_0.<ResolveSingletonConsumingService>b__0(IServiceProvider provider) in C:\Repos\RabbitMQ.Client.Core.DependencyInjection\src\RabbitMQ.Client.Core.DependencyInjection\RabbitMqClientDependencyInjectionExtensions.cs:line 291
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__9.MoveNext()
This exception was originally thrown at this call stack:
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(System.Exception)
System.Net.Sockets.Socket.EndConnect(System.IAsyncResult)
System.Net.Sockets.Socket.ConnectAsync.AnonymousMethod__275_0(System.IAsyncResult)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
RabbitMQ.Client.Impl.TcpClientAdapter.ConnectAsync(string, int)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
...
[Call Stack Truncated]
Inner Exception 1:
BrokerUnreachableException: None of the specified endpoints were reachable
Inner Exception 2:
AggregateException: One or more errors occurred. (Connection failed)
Inner Exception 3:
ConnectFailureException: Connection failed
Inner Exception 4:
ExtendedSocketException: No connection could be made because the target machine actively refused it. 127.0.0.1:5672
I was able to solve this by injecting a Lazy loaded dependency
StartUp
var rabbitMqSection = configuration.GetSection("rabbitMq");
var exchangeOptions = new RabbitMqExchangeOptions
{
Type = "fanout",
Durable = true
};
services.AddRabbitMqProducingClientSingleton(rabbitMqSection)
.AddProductionExchange("exchange", exchangeOptions);
// Allow to inject Lazy loaded instance for IProducingService
services.AddScoped(x => new Lazy<IProducingService>(() => x.GetRequiredService<IProducingService>()));
Implementation
public class EventPublisher
{
private readonly Lazy<IProducingService> _producingService;
public EventPublisher(Lazy<IProducingService> producingService)
{
_producingService = producingService;
}
public async Task PublishEvent()
{
await _producingService.Value.SendAsync(
@object: new { Message = "something" },
exchangeName: "exchange",
routingKey: "my.key");
}
}
@andrejt I am so late to answer that issue, but better later than never, right?
I'll start with a small story how this library even appeared. Some time ago I'd had to deal with rabbitMQ in one of my projects at work and I decided to create a small library that would help me with queue declarations and other stuff. I came up with simple idea to make a single QueueService
that would be responsible for all the work: both consumption and production of messages. That was a huge mistake. Simplicity took over common programming principles as single responsibility.
Same thing for declarations in constructor - simplicity is the key.
Then I posted this library at GitHub and NuGet without a hope that it will be useful to someone, but after people began to use it I started trying to avoid making breaking changes. And yeah, it is a mistake as well, coz I have to do it anyway.
There is an issue where I share my thoughts about reworking current paradigm of QueueService
, and here is a pull request where you can track upcoming changes.
I hope a new library version will come up in a week or so.
I think that it answers initial question, so I intend to close this issue. Feel free to re-open it if something is not clear and if the pull-request and connected issue do not satisfy your desires.
@fbridger I am happy you solved that problem by yourself!
Please take a look at this issue and the pull request too.
After an update that can change the way you use the library.
And if you have a suggestion (or a couple of them) feel free to leave them in the "Upcoming changes issue"
Isn't that a bit early and uncontrollable? If server is unavailable, the whole app might be blocking, even before logging is set up, so app could just crash without any information. Which may be a wanted effect, but I'd prefer keeping this more under control by moving StartClient() to a later stage, e.g. before StartConsuming(), or maybe even a separate method, exposed through IQueueService?