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; using Elsa.EntityFrameworkCore.Modules.Alterations; using Elsa.EntityFrameworkCore.Modules.Identity; using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.EntityFrameworkCore.Modules.Tenants; using Elsa.Extensions; using Elsa.Kafka.Factories; using Elsa.OpenTelemetry.Middleware; using Elsa.Secrets.Management.Tasks; using Elsa.Secrets.Persistence; using Elsa.Server.Web; using Elsa.Server.Web.Messages; using Elsa.Workflows; using Elsa.Workflows.IncidentStrategies; using Elsa.Workflows.LogPersistence; using Elsa.Workflows.Management; using Elsa.Workflows.Options; using Elsa.Workflows.Runtime.Distributed.Extensions; using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.Runtime.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using San.MongoLogger; using San.MongoLogger.Models; 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? configureCache) { //var configuration = new ConfigurationBuilder() // .AddJsonFile(appsettingName, optional: false, reloadOnChange: true) // .Build(); //var sqlServerConnectionString = configuration.GetConnectionString("SqlServer")!; var sqlDatabaseProvider = Enum.Parse("SqlServer"); const bool useDbContextPooling = false; const bool runEFCoreMigrations = true; const bool useReadOnlyMode = false; const WorkflowRuntime workflowRuntime = WorkflowRuntime.Distributed; const bool disableVariableWrappers = false; const bool disableVariableCopying = false; // Optionally create type aliases for easier configuration. TypeAliasRegistry.RegisterAlias("OrderReceivedProducerFactory", typeof(GenericProducerFactory)); TypeAliasRegistry.RegisterAlias("OrderReceivedConsumerFactory", typeof(GenericConsumerFactory)); // Add Elsa services. builder.Services.AddScoped(); builder.Services.AddMongoLogger(builder.Configuration); 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()); workflows.WithDefaultActivityExecutionPipeline(pipeline => pipeline.UseActivityExecutionTracing()); workflows.UseCommitStrategies(strategies => { strategies.AddStandardStrategies(); //می خوایم سریع انجام شه //strategies.Add("Every 10 seconds", new PeriodicWorkflowStrategy(TimeSpan.FromSeconds(10))); }); }) .UseWorkflowManagement(management => { management.UseEntityFrameworkCore(ef => { ef.UseSqlServer(sqlServerConnectionString); }); management.UseCache(); management.SetDefaultLogPersistenceMode(LogPersistenceMode.Inherit); management.UseReadOnlyMode(useReadOnlyMode); management.AddVariableTypeAndAlias("Application"); }) .UseWorkflowRuntime(runtime => { runtime.UseEntityFrameworkCore(ef => { ef.UseContextPooling = useDbContextPooling; var migrationsAssembly = typeof(Elsa.EntityFrameworkCore.SqlServer.IdentityDbContextFactory).Assembly; var connectionString = sqlServerConnectionString; ef.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlServer(migrationsAssembly, connectionString, null, configure => configure.CommandTimeout(60000)); ef.RunMigrations = runEFCoreMigrations; }); if (workflowRuntime == WorkflowRuntime.Distributed) { runtime.UseDistributedRuntime(); } runtime.UseCache(); runtime.UseConfiguredDistributedLocking(builder.Configuration); }) .UseCSharp(options => { options.DisableWrappers = disableVariableWrappers; //options.AppendScript("string Greet(string name) => $\"Hello {name}!\";"); //options.AppendScript("string SayHelloWorld() => Greet(\"World\");"); }) .UseJavaScript(options => { options.AllowClrAccess = true; options.DisableWrappers = disableVariableWrappers; options.DisableVariableCopying = disableVariableCopying; options.RegisterType(); //options.ConfigureEngine(engine => //{ // engine.Execute("function greet(name) { return `Hello ${name}!`; }"); // engine.Execute("function sayHelloWorld() { return greet('World'); }"); //}); }) // برای ثبت Activityهایی مانند Elsa.SendHttpRequest .UseHttp(http => http.UseCache()) .UseWorkflowContexts(); }); // Optionally configure recurring tasks using alternative schedules. builder.Services.Configure(options => { options.Schedule.ConfigureTask(TimeSpan.FromSeconds(300)); options.Schedule.ConfigureTask(TimeSpan.FromSeconds(300)); options.Schedule.ConfigureTask(TimeSpan.FromHours(4)); options.Schedule.ConfigureTask(TimeSpan.FromSeconds(15)); }); builder.Services.Configure(options => { options.InactivityThreshold = TimeSpan.FromSeconds(15); }); builder.Services.Configure(options => options.Ttl = TimeSpan.FromSeconds(10)); builder.Services.Configure(options => options.DefaultIncidentStrategy = typeof(ContinueWithIncidentsStrategy)); //builder.Services.AddHealthChecks(); builder.Services.AddScoped(); } public static void UseWorkflowFramework(this IApplicationBuilder app) { //try //{ // app.UseMongoLogger(); //} //catch (Exception ex) //{ // var d = ex; //} // Configure the pipeline. var env = app.ApplicationServices.GetRequiredService(); if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); // Health checks. //app.MapHealthChecks("/"); // Captures unhandled exceptions and returns a JSON response. app.UseJsonSerializationErrorHandler(); app.UseWorkflows(); } }