configure Redis cache and distributed locks
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
using Caspian.WorkflowFramework.Contracts;
|
||||
using Caspian.WorkflowFramework.Contracts;
|
||||
using Caspian.WorkflowFramework.Services;
|
||||
using Elsa.Caching.Options;
|
||||
using Elsa.Caching.Features;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Caspian.WorkflowFramework.Config;
|
||||
using Elsa.Common.RecurringTasks;
|
||||
using Elsa.Common.Serialization;
|
||||
using Elsa.EntityFrameworkCore.Extensions;
|
||||
@@ -36,6 +39,10 @@ namespace Caspian.WorkflowFramework;
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static void AddWorkflowFramework(this IHostApplicationBuilder builder, string sqlServerConnectionString)
|
||||
=> builder.AddWorkflowFramework(sqlServerConnectionString, null);
|
||||
|
||||
public static void AddWorkflowFramework(this IHostApplicationBuilder builder, string sqlServerConnectionString,
|
||||
Action<CacheFeature>? configureCache)
|
||||
{
|
||||
//var configuration = new ConfigurationBuilder()
|
||||
// .AddJsonFile(appsettingName, optional: false, reloadOnChange: true)
|
||||
@@ -45,7 +52,7 @@ public static class DependencyInjection
|
||||
var sqlDatabaseProvider = Enum.Parse<SqlDatabaseProvider>("SqlServer");
|
||||
const bool useDbContextPooling = false;
|
||||
const bool runEFCoreMigrations = true;
|
||||
const bool useCaching = true;
|
||||
|
||||
const bool useReadOnlyMode = false;
|
||||
const WorkflowRuntime workflowRuntime = WorkflowRuntime.Distributed;
|
||||
const bool disableVariableWrappers = false;
|
||||
@@ -63,6 +70,13 @@ public static class DependencyInjection
|
||||
builder.Services.AddElsa(elsa =>
|
||||
{
|
||||
elsa
|
||||
.UseCaching(cache =>
|
||||
{
|
||||
cache.Duration = TimeSpan.FromDays(1);
|
||||
cache.RegisterRedis();
|
||||
cache.UseConfiguration(builder.Configuration.GetSection("Workflow:Cache"));
|
||||
configureCache?.Invoke(cache);
|
||||
})
|
||||
.UseWorkflows(workflows =>
|
||||
{
|
||||
workflows.WithDefaultWorkflowExecutionPipeline(pipeline => pipeline.UseWorkflowExecutionTracing());
|
||||
@@ -81,8 +95,7 @@ public static class DependencyInjection
|
||||
ef.UseSqlServer(sqlServerConnectionString);
|
||||
});
|
||||
|
||||
if (useCaching)
|
||||
management.UseCache();
|
||||
management.UseCache();
|
||||
|
||||
management.SetDefaultLogPersistenceMode(LogPersistenceMode.Inherit);
|
||||
management.UseReadOnlyMode(useReadOnlyMode);
|
||||
@@ -106,8 +119,8 @@ public static class DependencyInjection
|
||||
runtime.UseDistributedRuntime();
|
||||
}
|
||||
|
||||
if (useCaching)
|
||||
runtime.UseCache();
|
||||
runtime.UseCache();
|
||||
runtime.UseConfiguredDistributedLocking(builder.Configuration);
|
||||
})
|
||||
.UseCSharp(options =>
|
||||
{
|
||||
@@ -128,7 +141,7 @@ public static class DependencyInjection
|
||||
//});
|
||||
})
|
||||
// برای ثبت Activityهایی مانند Elsa.SendHttpRequest
|
||||
.UseHttp()
|
||||
.UseHttp(http => http.UseCache())
|
||||
.UseWorkflowContexts();
|
||||
});
|
||||
|
||||
@@ -143,7 +156,7 @@ public static class DependencyInjection
|
||||
|
||||
builder.Services.Configure<RuntimeOptions>(options => { options.InactivityThreshold = TimeSpan.FromSeconds(15); });
|
||||
builder.Services.Configure<BookmarkQueuePurgeOptions>(options => options.Ttl = TimeSpan.FromSeconds(10));
|
||||
builder.Services.Configure<CachingOptions>(options => options.CacheDuration = TimeSpan.FromDays(1));
|
||||
|
||||
builder.Services.Configure<IncidentOptions>(options => options.DefaultIncidentStrategy = typeof(ContinueWithIncidentsStrategy));
|
||||
//builder.Services.AddHealthChecks();
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Medallion.Threading;
|
||||
|
||||
namespace Caspian.WorkflowFramework.Config;
|
||||
|
||||
internal class PrefixedDistributedLockProvider(IDistributedLockProvider provider, string prefix) : IDistributedLockProvider
|
||||
{
|
||||
public IDistributedLock CreateLock(string name) => provider.CreateLock(prefix + name);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
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<int?>("Database")
|
||||
?? legacySettings.GetValue<int?>("Database")
|
||||
?? configuration.GetValue<int?>("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<IConnectionMultiplexer>().GetDatabase(database)), prefix);
|
||||
break;
|
||||
}
|
||||
case null:
|
||||
case "":
|
||||
case "FILE":
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unsupported workflow lock provider '{providerName}'. Configure File or Redis.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user