From 885365df768b2d3a68763aee40f95be7f3b39dc9 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 27 Jul 2026 12:58:49 +0200 Subject: [PATCH] Add RabbitMQ support with configuration and connection Added support for RabbitMQ integration: - Updated project to target `net462` and `net8.0`. - Added NuGet dependencies: `RabbitMQ.Client`, `Microsoft.Extensions.Logging.Abstractions`, and `Microsoft.Extensions.Options.ConfigurationExtensions`. - Introduced `RabbitMqConfiguration` class for managing RabbitMQ settings. - Implemented `RabbitMqConnectionFactory` for creating and managing RabbitMQ connections with lazy initialization, async disposal, and logging support. --- ...gitalData.MessagingService.RabbitMQ.csproj | 2 + .../RabbitMqConfiguration.cs | 55 +++++++++++++ .../RabbitMqConnectionFactory.cs | 82 +++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 src/DigitalData.MessagingService.RabbitMQ/RabbitMqConfiguration.cs create mode 100644 src/DigitalData.MessagingService.RabbitMQ/RabbitMqConnectionFactory.cs diff --git a/src/DigitalData.MessagingService.RabbitMQ/DigitalData.MessagingService.RabbitMQ.csproj b/src/DigitalData.MessagingService.RabbitMQ/DigitalData.MessagingService.RabbitMQ.csproj index fd5f4bd..072ed0c 100644 --- a/src/DigitalData.MessagingService.RabbitMQ/DigitalData.MessagingService.RabbitMQ.csproj +++ b/src/DigitalData.MessagingService.RabbitMQ/DigitalData.MessagingService.RabbitMQ.csproj @@ -5,7 +5,9 @@ + + diff --git a/src/DigitalData.MessagingService.RabbitMQ/RabbitMqConfiguration.cs b/src/DigitalData.MessagingService.RabbitMQ/RabbitMqConfiguration.cs new file mode 100644 index 0000000..d8d5776 --- /dev/null +++ b/src/DigitalData.MessagingService.RabbitMQ/RabbitMqConfiguration.cs @@ -0,0 +1,55 @@ +namespace DigitalData.MessagingService.RabbitMQ +{ + /// + /// Configuration for RabbitMQ connection + /// + public class RabbitMqConfiguration + { + /// + /// Configuration section name in appsettings.json + /// + public const string SectionName = "RabbitMQ"; + + /// + /// RabbitMQ server hostname + /// + public string HostName { get; set; } = "localhost"; + + /// + /// RabbitMQ AMQP port (default: 5672) + /// + public int Port { get; set; } = 5672; + + /// + /// RabbitMQ username + /// + public string UserName { get; set; } = "guest"; + + /// + /// RabbitMQ password + /// + public string Password { get; set; } = "guest"; + + /// + /// Virtual host (default: /) + /// + public string VirtualHost { get; set; } = "/"; + + /// + /// Enable automatic recovery on connection failure + /// + public bool AutomaticRecoveryEnabled { get; set; } = true; + + /// + /// Network recovery interval in seconds + /// + public int NetworkRecoveryIntervalSeconds { get; set; } = 10; + + public string QueueName { get; set; } + public string ExchangeName { get; set; } + public string RoutingKey { get; set; } + public string DlqQueueName { get; set; } + public string DlqExchangeName { get; set; } + public string DlqRoutingKey { get; set; } + } +} \ No newline at end of file diff --git a/src/DigitalData.MessagingService.RabbitMQ/RabbitMqConnectionFactory.cs b/src/DigitalData.MessagingService.RabbitMQ/RabbitMqConnectionFactory.cs new file mode 100644 index 0000000..f4d5817 --- /dev/null +++ b/src/DigitalData.MessagingService.RabbitMQ/RabbitMqConnectionFactory.cs @@ -0,0 +1,82 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using RabbitMQ.Client; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace DigitalData.MessagingService.RabbitMQ +{ + public sealed class RabbitMqConnectionFactory : IAsyncDisposable + { + private readonly RabbitMqConfiguration _config; + + private readonly ILogger +#if nullable +? +#endif + _logger; + + private readonly Lazy> _lazyConnectionProvider; + + private IConnection +#if nullable +? +#endif + _connection = null; + + private CancellationToken? _cancellationToken; + + public CancellationToken CancellationToken => _cancellationToken + ?? throw new InvalidOperationException("RabbitMqConnectionFactory is not initialized. Call InitAsync() before using this method."); + + public Task GetConnectionAsync() + { + if (_cancellationToken != null) + return _lazyConnectionProvider.Value; + else + throw new InvalidOperationException("RabbitMqConnectionFactory is not initialized. Call InitAsync() before using this method."); + } + + public RabbitMqConnectionFactory(IOptions config) + { + _config = config.Value; + _lazyConnectionProvider = new Lazy>(async () => + { + _cancellationToken?.ThrowIfCancellationRequested(); + var factory = new ConnectionFactory + { + HostName = _config.HostName, + Port = _config.Port, + UserName = _config.UserName, + Password = _config.Password, + VirtualHost = _config.VirtualHost, + AutomaticRecoveryEnabled = _config.AutomaticRecoveryEnabled, + NetworkRecoveryInterval = TimeSpan.FromSeconds(_config.NetworkRecoveryIntervalSeconds), + }; + + _connection = await factory.CreateConnectionAsync((CancellationToken)_cancellationToken +#if nullable +! +#endif + ); + return _connection; + }); + } + + public async Task InitAsync(CancellationToken cancellationToken = default) + { + _cancellationToken = cancellationToken; + _ = await GetConnectionAsync(); + } + + public async ValueTask DisposeAsync() + { + if (_connection != null) + { + await _connection.CloseAsync(); + await _connection.DisposeAsync(); + } + } + } +} \ No newline at end of file