using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Hosting.Management.Contracts; using Elsa.Hosting.Management.Features; using Elsa.MassTransit.Consumers; using Elsa.MassTransit.Extensions; using Elsa.MassTransit.Features; using Elsa.MassTransit.Options; using MassTransit; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace Elsa.MassTransit.RabbitMq.Features; /// /// Configures MassTransit to use the RabbitMQ transport. /// [DependsOn(typeof(MassTransitFeature))] [DependsOn(typeof(InstanceManagementFeature))] public class RabbitMqServiceBusFeature : FeatureBase { /// public RabbitMqServiceBusFeature(IModule module) : base(module) { } /// A RabbitMQ connection string. public string? ConnectionString { get; set; } /// /// Configures the RabbitMQ transport options. /// public Action? TransportOptions { get; set; } /// /// Configures the RabbitMQ bus. /// public Action? ConfigureServiceBus { get; set; } /// public override void Configure() { Module.Configure(massTransitFeature => { massTransitFeature.BusConfigurator = configure => { var temporaryConsumers = massTransitFeature.GetConsumers() .Where(c => c.IsTemporary) .ToList(); // Consumers need to be added before the UsingRabbitMq statement to prevent exceptions. foreach (var consumer in temporaryConsumers) configure.AddConsumer(consumer.ConsumerType).ExcludeFromConfigureEndpoints(); configure.UsingRabbitMq((context, configurator) => { var options = context.GetRequiredService>().Value; var instanceNameProvider = context.GetRequiredService(); if (!string.IsNullOrEmpty(ConnectionString)) configurator.Host(ConnectionString); if (options.PrefetchCount is not null) configurator.PrefetchCount = options.PrefetchCount.Value; configurator.ConcurrentMessageLimit = options.ConcurrentMessageLimit; ConfigureServiceBus?.Invoke(configurator); foreach (var consumer in temporaryConsumers) { configurator.ReceiveEndpoint($"{instanceNameProvider.GetName()}-{consumer.Name}", endpointConfigurator => { endpointConfigurator.QueueExpiration = options.TemporaryQueueTtl ?? TimeSpan.FromHours(1); endpointConfigurator.ConcurrentMessageLimit = options.ConcurrentMessageLimit; endpointConfigurator.Durable = false; endpointConfigurator.AutoDelete = true; endpointConfigurator.ConfigureConsumer(context, consumer.ConsumerType); }); } // Only configure the dispatcher endpoints if the Masstransit Workflow Dispatcher feature is enabled. if (Module.HasFeature()) configurator.SetupWorkflowDispatcherEndpoints(context); configurator.ConfigureEndpoints(context, new KebabCaseEndpointNameFormatter("Elsa", false)); }); }; }); } /// public override void Apply() { if (TransportOptions != null) Services.Configure(TransportOptions); } }