I want use AMQP connection string. I want to create a single shared connection (and channel per app lifetime to avoid resource exhaustion.
I found this way to do it:
public class RabbitMqService
{
private readonly string _rabbitMqConnectionString;
private IConnection? _connection;
private IChannel? _channel;
private readonly ILogger<RabbitMqService> _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
private bool _initialized = false;
public RabbitMqService(
IConfiguration configuration,
ILogger<RabbitMqService> logger,
IHttpContextAccessor httpContextAccessor
)
{
var rabbitMqSection = configuration.GetSection("RabbitMq");
_rabbitMqConnectionString = rabbitMqSection["ConnectionString"]!;
_logger = logger;
_httpContextAccessor = httpContextAccessor;
}
private string GetCorrelationId()
{
return _httpContextAccessor.HttpContext?.TraceIdentifier
?? Guid.NewGuid().ToString();
}
public async Task InitAsync()
{
if (_initialized && _connection?.IsOpen == true &&
_channel?.IsOpen == true)
return;
try
{
var factory = new ConnectionFactory
{
Uri = new Uri(_rabbitMqConnectionString)
};
_connection = await factory.CreateConnectionAsync();
_channel = await _connection.CreateChannelAsync();
_initialized = true;
}
catch (Exception ex)
{
_initialized = false;
string correlationId = GetCorrelationId();
_logger.LogError(ex,
"Error in RabbitMq initAsync| CorrelationId: {CorrelationId}",
correlationId
);
}
}
public async Task<IChannel> GetChannel()
{
if (_connection == null ||
!_connection.IsOpen ||
_channel == null || !_channel.IsOpen
)
{
_initialized = false;
await InitAsync();
}
if (_channel == null)
throw new InvalidOperationException(
"Failed to initialize RabbitMQ channel."
);
return _channel;
}
public async ValueTask DisposeAsync()
{
if (_channel is not null)
{
await _channel.CloseAsync();
}
if (_connection is not null)
{
await _connection.DisposeAsync();
}
}
}
And in the program.cs file:
builder.Services.AddSingleton<RabbitMqService>();
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var rabbitService = scope.ServiceProvider.GetRequiredService<RabbitMqService>();
await rabbitService.InitAsync();
}
If there is a better way please share it and THANK you very much.