using Elsa.Workflows.Runtime.Features; using Medallion.Threading.Redis; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using StackExchange.Redis; namespace Caspian.WorkflowFramework.Config; internal static class WorkflowRuntimeFeatureExtensions { internal static void UseConfiguredDistributedLocking(this WorkflowRuntimeFeature runtime, IConfiguration configuration) { var legacySettings = configuration.GetSection("Runtime:DistributedLocking"); var settings = configuration.GetSection("Workflow:Runtime:DistributedLocking"); runtime.DistributedLockingOptions = options => { legacySettings.Bind(options); settings.Bind(options); }; var providerName = settings["Provider"] ?? legacySettings["Provider"]; switch (providerName?.ToUpperInvariant()) { case "REDIS": { var database = settings.GetValue("Database") ?? legacySettings.GetValue("Database") ?? configuration.GetValue("Redis:Database") ?? -1; var prefix = settings["KeyPrefix"] ?? legacySettings["KeyPrefix"] ?? "nextbank:workflow:locks:"; if (database < -1) throw new InvalidOperationException("Workflow lock database must be -1 or a non-negative number."); if (string.IsNullOrWhiteSpace(prefix)) throw new InvalidOperationException("Workflow lock KeyPrefix must not be empty."); runtime.DistributedLockProvider = sp => new PrefixedDistributedLockProvider( new RedisDistributedSynchronizationProvider(sp.GetRequiredService().GetDatabase(database)), prefix); break; } case null: case "": case "FILE": break; default: throw new InvalidOperationException($"Unsupported workflow lock provider '{providerName}'. Configure File or Redis."); } } }