From 0f7d66b95edbad6a97266e0173a3c7066ce10e7e Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Wed, 30 Jun 2021 18:18:59 +0300 Subject: [PATCH 01/10] MongoDB and Postgres persistence configuration MongoDB and Postgres persistence configuration --- Elsa.sln | 28 ++- .../Elsa.Activities.Webhooks.csproj | 11 +- .../WebhookOptionsBuilderExtensions.cs | 20 +- .../Options/WebhookOptions.cs | 2 +- .../Elsa.Activities.Webhooks/Startup.cs | 4 +- ...ks.Persistence.EntityFramework.Core.csproj | 1 + .../EntityFrameworkWebhookStartupBase.cs | 47 ++++ .../WebhookServiceCollectionExtensions.cs | 229 ++++++++++++++++++ .../Startup.cs | 13 + ...ebhookDbContextOptionsBuilderExtensions.cs | 4 +- .../Startup.cs | 13 + .../Startup.cs | 13 + .../Startup.cs | 14 ++ .../WebhookServiceCollectionExtensions.cs | 8 +- .../Startup.cs | 31 +++ .../WebhookServiceCollectionExtensions.cs | 17 +- .../Startups.cs | 69 ++++++ .../Elsa.Samples.Server.Host.csproj | 4 + .../server/Elsa.Samples.Server.Host/README.md | 113 +++++++++ .../Elsa.Samples.Server.Host/Startup.cs | 22 +- .../Elsa.Samples.Server.Host/appsettings.json | 14 +- 21 files changed, 618 insertions(+), 59 deletions(-) create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Extensions/WebhookServiceCollectionExtensions.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/Startup.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.PostgreSql/Startup.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.SqlServer/Startup.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Sqlite/Startup.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs create mode 100644 src/samples/server/Elsa.Samples.Server.Host/README.md diff --git a/Elsa.sln b/Elsa.sln index 139a16bdf..615c1dc92 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -320,7 +320,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ElsaDashboard.Samples.Blazo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.FaultyWorkflows", "src\samples\aspnet\Elsa.Samples.FaultyWorkflows\Elsa.Samples.FaultyWorkflows.csproj", "{84751112-C2B7-41D4-98F5-D87D7C2E1DAE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Activities.Conductor", "src\activities\Elsa.Activities.Conductor\Elsa.Activities.Conductor.csproj", "{4D4022DD-244B-47EE-95FA-7071EC687B24}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Activities.Conductor", "src\activities\Elsa.Activities.Conductor\Elsa.Activities.Conductor.csproj", "{4D4022DD-244B-47EE-95FA-7071EC687B24}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aspnetcore", "aspnetcore", "{39DE1EE2-DF4F-44EB-9F5A-551BEADD6673}" EndProject @@ -652,6 +652,16 @@ Global {3DF05CFC-AC77-489F-9A42-C4FDB599AA69}.Release|Any CPU.Build.0 = Release|Any CPU {D55BC08B-CA82-478A-99F7-EDE90AC33160}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D55BC08B-CA82-478A-99F7-EDE90AC33160}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D55BC08B-CA82-478A-99F7-EDE90AC33160}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D55BC08B-CA82-478A-99F7-EDE90AC33160}.Release|Any CPU.Build.0 = Release|Any CPU + {775EFD59-F99C-4D38-B54E-9734C9D9649A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {775EFD59-F99C-4D38-B54E-9734C9D9649A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {775EFD59-F99C-4D38-B54E-9734C9D9649A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {775EFD59-F99C-4D38-B54E-9734C9D9649A}.Release|Any CPU.Build.0 = Release|Any CPU + {30A9B140-14F5-4D00-84ED-1447F96D13C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30A9B140-14F5-4D00-84ED-1447F96D13C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30A9B140-14F5-4D00-84ED-1447F96D13C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30A9B140-14F5-4D00-84ED-1447F96D13C8}.Release|Any CPU.Build.0 = Release|Any CPU {BE284508-9582-4FCB-B0DD-0761AB940AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE284508-9582-4FCB-B0DD-0761AB940AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {BE284508-9582-4FCB-B0DD-0761AB940AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -660,10 +670,6 @@ Global {3EB488DF-3C28-4DAD-B43E-6062E39629AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {3EB488DF-3C28-4DAD-B43E-6062E39629AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {3EB488DF-3C28-4DAD-B43E-6062E39629AB}.Release|Any CPU.Build.0 = Release|Any CPU - {775EFD59-F99C-4D38-B54E-9734C9D9649A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {775EFD59-F99C-4D38-B54E-9734C9D9649A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30A9B140-14F5-4D00-84ED-1447F96D13C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30A9B140-14F5-4D00-84ED-1447F96D13C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E2423CF-50E6-4D2B-8749-17B1EF540FE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3E2423CF-50E6-4D2B-8749-17B1EF540FE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E2423CF-50E6-4D2B-8749-17B1EF540FE4}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -678,8 +684,12 @@ Global {9ACA06DA-9AFE-41A2-8109-EFED8B9B14A1}.Release|Any CPU.Build.0 = Release|Any CPU {D1644D32-AA51-4D10-942E-F2722DB963B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1644D32-AA51-4D10-942E-F2722DB963B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1644D32-AA51-4D10-942E-F2722DB963B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1644D32-AA51-4D10-942E-F2722DB963B4}.Release|Any CPU.Build.0 = Release|Any CPU {7756E22A-AD59-46C1-A019-1D28D7217347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7756E22A-AD59-46C1-A019-1D28D7217347}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7756E22A-AD59-46C1-A019-1D28D7217347}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7756E22A-AD59-46C1-A019-1D28D7217347}.Release|Any CPU.Build.0 = Release|Any CPU {7B84277D-96EF-4C7F-9D5E-8CBB2D26E5EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B84277D-96EF-4C7F-9D5E-8CBB2D26E5EB}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B84277D-96EF-4C7F-9D5E-8CBB2D26E5EB}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -722,6 +732,8 @@ Global {EE147504-555D-4EFC-A79A-34748666AA6C}.Release|Any CPU.Build.0 = Release|Any CPU {1129868E-BA72-44C4-941C-A28D9001504B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1129868E-BA72-44C4-941C-A28D9001504B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1129868E-BA72-44C4-941C-A28D9001504B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1129868E-BA72-44C4-941C-A28D9001504B}.Release|Any CPU.Build.0 = Release|Any CPU {24A99602-F743-4B1A-AC96-599F34AE916C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {24A99602-F743-4B1A-AC96-599F34AE916C}.Debug|Any CPU.Build.0 = Debug|Any CPU {24A99602-F743-4B1A-AC96-599F34AE916C}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -847,13 +859,14 @@ Global {B09A6E42-EF42-4693-BA0E-5EE1D7F81FFD} = {DBBD242E-4437-4BDB-919F-A70839BE75FA} {495BE954-E6EA-41A9-8054-A5CA5DD0924E} = {DBBD242E-4437-4BDB-919F-A70839BE75FA} {D86B94DC-A53C-4A67-A820-828DD359C49B} = {4673732F-2853-47BD-91B8-C95C229D2C89} + {F1EF5639-021A-4D22-9D4A-73D57C88EBFA} = {39DE1EE2-DF4F-44EB-9F5A-551BEADD6673} {3A30EFFE-32D8-40B8-9C62-427037BB5424} = {EEBEA8AF-C8A8-4C71-A96C-D5836DE24359} {3DF05CFC-AC77-489F-9A42-C4FDB599AA69} = {8B6B40A8-DF21-4CD2-BABD-474B79D0C3AF} {D55BC08B-CA82-478A-99F7-EDE90AC33160} = {C865B0FD-E505-48F0-BFAF-0D4D7C1B5CA1} - {BE284508-9582-4FCB-B0DD-0761AB940AD7} = {B43B546E-23F3-46E8-ACB7-D04F05CDA180} - {3EB488DF-3C28-4DAD-B43E-6062E39629AB} = {FC9F520F-BA51-4AD2-BFEE-EF787798E734} {775EFD59-F99C-4D38-B54E-9734C9D9649A} = {22E75696-6FE9-436A-9097-EE21C603F818} {30A9B140-14F5-4D00-84ED-1447F96D13C8} = {FC9F520F-BA51-4AD2-BFEE-EF787798E734} + {BE284508-9582-4FCB-B0DD-0761AB940AD7} = {B43B546E-23F3-46E8-ACB7-D04F05CDA180} + {3EB488DF-3C28-4DAD-B43E-6062E39629AB} = {FC9F520F-BA51-4AD2-BFEE-EF787798E734} {3E2423CF-50E6-4D2B-8749-17B1EF540FE4} = {22E75696-6FE9-436A-9097-EE21C603F818} {9937FB02-72D9-4FCD-B31E-8E60CFF1B37F} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925} {61C16CA0-B190-4642-A81A-5C03705CA2C1} = {9937FB02-72D9-4FCD-B31E-8E60CFF1B37F} @@ -879,7 +892,6 @@ Global {84751112-C2B7-41D4-98F5-D87D7C2E1DAE} = {22E75696-6FE9-436A-9097-EE21C603F818} {4D4022DD-244B-47EE-95FA-7071EC687B24} = {B43B546E-23F3-46E8-ACB7-D04F05CDA180} {39DE1EE2-DF4F-44EB-9F5A-551BEADD6673} = {4673732F-2853-47BD-91B8-C95C229D2C89} - {F1EF5639-021A-4D22-9D4A-73D57C88EBFA} = {39DE1EE2-DF4F-44EB-9F5A-551BEADD6673} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158} diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Elsa.Activities.Webhooks.csproj b/src/activities/webhooks/Elsa.Activities.Webhooks/Elsa.Activities.Webhooks.csproj index 558da474f..17f6b2faf 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Elsa.Activities.Webhooks.csproj +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Elsa.Activities.Webhooks.csproj @@ -1,4 +1,4 @@ - + @@ -12,6 +12,10 @@ elsa, workflows, webhooks + + + + @@ -22,11 +26,6 @@ - - - - - diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookOptionsBuilderExtensions.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookOptionsBuilderExtensions.cs index 8cf27357c..cdb5e79f5 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookOptionsBuilderExtensions.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookOptionsBuilderExtensions.cs @@ -1,34 +1,18 @@ -using System; using Elsa.Activities.Webhooks.ActivityTypes; using Elsa.Activities.Webhooks.Bookmarks; -using Elsa.Activities.Webhooks.Persistence.Decorators; using Elsa.Services; -using Elsa.Webhooks.Persistence; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Activities.Webhooks.Extensions { public static class WebhookOptionsBuilderExtensions { - public static ElsaOptionsBuilder AddWebhooks( - this ElsaOptionsBuilder elsaOptions, - Action? configure = default) + public static ElsaOptionsBuilder AddWebhooks(this ElsaOptionsBuilder elsaOptions) { - var services = elsaOptions.Services; - - // Configure Webhooks. - var webhookOptionsBuilder = new WebhookOptionsBuilder(elsaOptions.Services); - configure?.Invoke(webhookOptionsBuilder); - - // Services. - services + elsaOptions.Services .AddScoped() - .AddScoped(sp => webhookOptionsBuilder.WebhookOptions.WebhookDefinitionStoreFactory(sp)) .AddBookmarkProvider(); - services.Decorate(); - services.Decorate(); - return elsaOptions; } diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Options/WebhookOptions.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Options/WebhookOptions.cs index 8231b029b..38a6bc577 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Options/WebhookOptions.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Options/WebhookOptions.cs @@ -12,6 +12,6 @@ namespace Elsa.Activities.Webhooks.Options WebhookDefinitionStoreFactory = provider => ActivatorUtilities.CreateInstance(provider); } - internal Func WebhookDefinitionStoreFactory { get; set; } + public Func WebhookDefinitionStoreFactory { get; set; } } } diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Startup.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Startup.cs index 8ef7a7437..74c656e6c 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Startup.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Startup.cs @@ -1,7 +1,6 @@ using Elsa.Activities.Webhooks.Extensions; using Elsa.Attributes; using Elsa.Services.Startup; -using Elsa.Webhooks.Persistence.EntityFramework.Sqlite; using Microsoft.Extensions.Configuration; namespace Elsa.Activities.Webhooks @@ -11,8 +10,7 @@ namespace Elsa.Activities.Webhooks { public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) { - // TODO: Read selected persistence provider from config. - elsa.AddWebhooks(webhooks => webhooks.UseEntityFrameworkPersistence(ef => ef.UseWebhookSqlite())); + elsa.AddWebhooks(); } } } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Elsa.Webhooks.Persistence.EntityFramework.Core.csproj b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Elsa.Webhooks.Persistence.EntityFramework.Core.csproj index f35f7aca7..c6b9f6818 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Elsa.Webhooks.Persistence.EntityFramework.Core.csproj +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Elsa.Webhooks.Persistence.EntityFramework.Core.csproj @@ -19,6 +19,7 @@ + diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs new file mode 100644 index 000000000..cb2ae5b18 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs @@ -0,0 +1,47 @@ +using System; +using Elsa.Activities.Webhooks; +using Elsa.Activities.Webhooks.Persistence.Decorators; +using Elsa.Services.Startup; +using Elsa.Webhooks.Persistence.EntityFramework.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Webhooks.Persistence.EntityFramework.Core +{ + public abstract class EntityFrameworkWebhookStartupBase : StartupBase + { + protected abstract string ProviderName { get; } + + public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) + { + var services = elsa.Services; + var section = configuration.GetSection($"Elsa:Persistence:{ProviderName}"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); + + if (string.IsNullOrWhiteSpace(connectionString)) + { + if (string.IsNullOrWhiteSpace(connectionStringName)) + connectionStringName = ProviderName; + + connectionString = configuration.GetConnectionString(connectionStringName); + } + + if (string.IsNullOrWhiteSpace(connectionString)) + connectionString = GetDefaultConnectionString(); + + var webhookOptionsBuilder = new WebhookOptionsBuilder(elsa.Services); + webhookOptionsBuilder.UseEntityFrameworkPersistence(options => Configure(options, connectionString)); + + services.AddScoped(sp => webhookOptionsBuilder.WebhookOptions.WebhookDefinitionStoreFactory(sp)); + + services.Decorate(); + services.Decorate(); + } + + protected virtual string GetDefaultConnectionString() => throw new Exception($"No connection string specified for the {ProviderName} provider"); + protected abstract void Configure(DbContextOptionsBuilder options, string connectionString); + + } +} \ No newline at end of file diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Extensions/WebhookServiceCollectionExtensions.cs new file mode 100644 index 000000000..42109a562 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/Extensions/WebhookServiceCollectionExtensions.cs @@ -0,0 +1,229 @@ +using System; +using Elsa.Activities.Webhooks; +using Elsa.Persistence.EntityFramework.Core; +using Elsa.Runtime; +using Elsa.Webhooks.Persistence.EntityFramework.Core.Services; +using Elsa.Webhooks.Persistence.EntityFramework.Core.StartupTasks; +using Elsa.Webhooks.Persistence.EntityFramework.Core.Stores; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Webhooks.Persistence.EntityFramework.Core.Extensions +{ + public static class WebhookServiceCollectionExtensions + { + /// + /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. + /// + /// + /// + /// Pooled DB Context instances is a performance optimisation which is documented in more detail at + /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. + /// + /// + /// An Elsa options builder + /// A configuration builder callback + /// If true then database migrations will be auto-executed on startup + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + bool autoRunMigrations = true) => + webhookOptions.UseEntityFrameworkPersistence(configure, autoRunMigrations); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. + /// + /// + /// + /// Pooled DB Context instances is a performance optimisation which is documented in more detail at + /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. + /// + /// + /// An Elsa options builder + /// A configuration builder callback + /// If true then database migrations will be auto-executed on startup + /// The concrete type of to use. + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + bool autoRunMigrations = true) where TWebhookContext : WebhookContext => + webhookOptions.UseEntityFrameworkPersistence((_, builder) => configure(builder), autoRunMigrations); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. + /// + /// + /// + /// Pooled DB Context instances is a performance optimisation which is documented in more detail at + /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. + /// + /// + /// An Elsa options builder + /// A configuration builder callback, which also provides access to a service provider + /// If true then database migrations will be auto-executed on startup + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + bool autoRunMigrations = true) => + webhookOptions.UseEntityFrameworkPersistence(configure, autoRunMigrations); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. + /// + /// + /// + /// Pooled DB Context instances is a performance optimisation which is documented in more detail at + /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. + /// + /// + /// An Elsa options builder + /// A configuration builder callback, which also provides access to a service provider + /// If true then database migrations will be auto-executed on startup + /// The concrete type of to use. + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + bool autoRunMigrations = true) where TWebhookContext : WebhookContext => + UseEntityFrameworkPersistence(webhookOptions, configure, autoRunMigrations, true, ServiceLifetime.Singleton); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. + /// + /// + /// + /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant + /// application, where re-use of DB Context objects is impractical. + /// + /// + /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of + /// the DB Context may differ, it is not feasible to try to automatically migrate them. + /// Your application is ultimately responsible for executing the contents of the class in a manner + /// which is suitable for your use-case. + /// + /// + /// An Elsa options builder + /// A configuration builder callback + /// The service lifetime which will be used for each DB Context instance + /// If true then database migrations will be auto-executed on startup + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, + bool autoRunMigrations = false) => + webhookOptions.UseNonPooledEntityFrameworkPersistence(configure, serviceLifetime, autoRunMigrations); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. + /// + /// + /// + /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant + /// application, where re-use of DB Context objects is impractical. + /// + /// + /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of + /// the DB Context may differ, it is not feasible to try to automatically migrate them. + /// Your application is ultimately responsible for executing the contents of the class in a manner + /// which is suitable for your use-case. + /// + /// + /// An Elsa options builder + /// A configuration builder callback + /// The service lifetime which will be used for each DB Context instance + /// If true then database migrations will be auto-executed on startup + /// The concrete type of to use. + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, + bool autoRunMigrations = false) where TWebhookContext : WebhookContext => + webhookOptions.UseNonPooledEntityFrameworkPersistence((_, builder) => configure(builder), serviceLifetime, autoRunMigrations); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. + /// + /// + /// + /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant + /// application, where re-use of DB Context objects is impractical. + /// + /// + /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of + /// the DB Context may differ, it is not feasible to try to automatically migrate them. + /// Your application is ultimately responsible for executing the contents of the class in a manner + /// which is suitable for your use-case. + /// + /// + /// An Elsa options builder + /// A configuration builder callback, which also provides access to a service provider + /// The service lifetime which will be used for each DB Context instance + /// If true then database migrations will be auto-executed on startup + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, + bool autoRunMigrations = false) => + webhookOptions.UseNonPooledEntityFrameworkPersistence(configure, serviceLifetime, autoRunMigrations); + + /// + /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. + /// + /// + /// + /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant + /// application, where re-use of DB Context objects is impractical. + /// + /// + /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of + /// the DB Context may differ, it is not feasible to try to automatically migrate them. + /// Your application is ultimately responsible for executing the contents of the class in a manner + /// which is suitable for your use-case. + /// + /// + /// An Elsa options builder + /// A configuration builder callback, which also provides access to a service provider + /// The service lifetime which will be used for each DB Context instance + /// If true then database migrations will be auto-executed on startup + /// The concrete type of to use. + /// The Elsa options builder, so calls may be chained + public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, + Action configure, + ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, + bool autoRunMigrations = false) where TWebhookContext : WebhookContext => + UseEntityFrameworkPersistence(webhookOptions, configure, autoRunMigrations, false, serviceLifetime); + + static WebhookOptionsBuilder UseEntityFrameworkPersistence(WebhookOptionsBuilder webhookOptions, + Action configure, + bool autoRunMigrations, + bool useContextPooling, + ServiceLifetime serviceLifetime) where TWebhookContext : WebhookContext + { + /* Auto-running migrations is intentionally unavailable when not using context pooling. + * When we aren't using pooling then it probably means that each DB Context is different + * in some manner. That could easily mean the connection strings (IE: Contexts might not + * all connect to the same DB). In that case, without further logic (which can't be + * pre-empted by Elsa), we can't be sure we're connecting to the right DBs when running + * migrations. + * + * It's much more sane just to explicitly not-support it and leave it to the app developer. + * They can run their own migrations in line with their own logic. + */ + + if (useContextPooling) + webhookOptions.Services.AddPooledDbContextFactory(configure); + else + webhookOptions.Services.AddDbContextFactory(configure, serviceLifetime); + + webhookOptions.Services + .AddSingleton>() + .AddScoped(); + + if (autoRunMigrations) + webhookOptions.Services.AddStartupTask(); + + webhookOptions.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); + + return webhookOptions; + } + } +} diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/Startup.cs new file mode 100644 index 000000000..90496e3c0 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/Startup.cs @@ -0,0 +1,13 @@ +using Elsa.Attributes; +using Elsa.Webhooks.Persistence.EntityFramework.Core; +using Microsoft.EntityFrameworkCore; + +namespace Elsa.Webhooks.Persistence.EntityFramework.MySql +{ + [Feature("Webhooks:Persistence:EntityFrameworkCore:MySql")] + public class Startup : EntityFrameworkWebhookStartupBase + { + protected override string ProviderName => "MySql"; + protected override void Configure(DbContextOptionsBuilder options, string connectionString) => options.UseWebhookMySql(connectionString); + } +} \ No newline at end of file diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/WebhookDbContextOptionsBuilderExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/WebhookDbContextOptionsBuilderExtensions.cs index 1dbaccb4e..6921fd63b 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/WebhookDbContextOptionsBuilderExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.MySql/WebhookDbContextOptionsBuilderExtensions.cs @@ -1,5 +1,6 @@ using Elsa.Webhooks.Persistence.EntityFramework.Core; using Microsoft.EntityFrameworkCore; +using Pomelo.EntityFrameworkCore.MySql.Infrastructure; namespace Elsa.Webhooks.Persistence.EntityFramework.MySql { @@ -11,6 +12,7 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.MySql public static DbContextOptionsBuilder UseWebhookMySql(this DbContextOptionsBuilder builder, string connectionString) => builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), db => db .MigrationsAssembly(typeof(WebhookMySqlElsaContextFactory).Assembly.GetName().Name) - .MigrationsHistoryTable(WebhookContext.MigrationsHistoryTable, WebhookContext.ElsaSchema)); + .MigrationsHistoryTable(WebhookContext.MigrationsHistoryTable, WebhookContext.ElsaSchema) + .SchemaBehavior(MySqlSchemaBehavior.Ignore)); } } \ No newline at end of file diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.PostgreSql/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.PostgreSql/Startup.cs new file mode 100644 index 000000000..c141f08c6 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.PostgreSql/Startup.cs @@ -0,0 +1,13 @@ +using Elsa.Attributes; +using Elsa.Webhooks.Persistence.EntityFramework.Core; +using Microsoft.EntityFrameworkCore; + +namespace Elsa.Webhooks.Persistence.EntityFramework.PostgreSql +{ + [Feature("Webhooks:Persistence:EntityFrameworkCore:PostgreSql")] + public class Startup : EntityFrameworkWebhookStartupBase + { + protected override string ProviderName => "PostgreSql"; + protected override void Configure(DbContextOptionsBuilder options, string connectionString) => options.UseWebhookPostgreSql(connectionString); + } +} \ No newline at end of file diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.SqlServer/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.SqlServer/Startup.cs new file mode 100644 index 000000000..6557a7350 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.SqlServer/Startup.cs @@ -0,0 +1,13 @@ +using Elsa.Attributes; +using Elsa.Webhooks.Persistence.EntityFramework.Core; +using Microsoft.EntityFrameworkCore; + +namespace Elsa.Webhooks.Persistence.EntityFramework.SqlServer +{ + [Feature("Webhooks:Persistence:EntityFrameworkCore:SqlServer")] + public class Startup : EntityFrameworkWebhookStartupBase + { + protected override string ProviderName => "SqlServer"; + protected override void Configure(DbContextOptionsBuilder options, string connectionString) => options.UseWebhookSqlServer(connectionString); + } +} \ No newline at end of file diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Sqlite/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Sqlite/Startup.cs new file mode 100644 index 000000000..07b50dcc6 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Sqlite/Startup.cs @@ -0,0 +1,14 @@ +using Elsa.Attributes; +using Elsa.Webhooks.Persistence.EntityFramework.Core; +using Microsoft.EntityFrameworkCore; + +namespace Elsa.Webhooks.Persistence.EntityFramework.Sqlite +{ + [Feature("Webhooks:Persistence:EntityFrameworkCore:Sqlite")] + public class Startup : EntityFrameworkWebhookStartupBase + { + protected override string ProviderName => "Sqlite"; + protected override string GetDefaultConnectionString() => "Data Source=elsa.sqlite.db;Cache=Shared;"; + protected override void Configure(DbContextOptionsBuilder options, string connectionString) => options.UseWebhookSqlite(connectionString); + } +} \ No newline at end of file diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs index e456cc35c..07fcd14cd 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs @@ -11,9 +11,9 @@ namespace Elsa.Webhooks.Persistence.MongoDb.Extensions { public static class WebhookServiceCollectionExtensions { - public static ElsaOptionsBuilder UseMongoDbPersistence(this ElsaOptionsBuilder elsa, Action configureOptions) => UseMongoDbPersistence(elsa, configureOptions); + public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, Action configureOptions) => UseWebhookMongoDbPersistence(elsa, configureOptions); - public static ElsaOptionsBuilder UseMongoDbPersistence(this ElsaOptionsBuilder elsa, Action configureOptions) where TDbContext : ElsaMongoDbContext + public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, Action configureOptions) where TDbContext : ElsaMongoDbContext { AddCore(elsa); elsa.Services.Configure(configureOptions); @@ -21,9 +21,9 @@ namespace Elsa.Webhooks.Persistence.MongoDb.Extensions return elsa; } - public static ElsaOptionsBuilder UseMongoDbPersistence(this ElsaOptionsBuilder elsa, IConfiguration configuration) => UseMongoDbPersistence(elsa, configuration); + public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, IConfiguration configuration) => UseWebhookMongoDbPersistence(elsa, configuration); - public static ElsaOptionsBuilder UseMongoDbPersistence(this ElsaOptionsBuilder elsa, IConfiguration configuration) where TDbContext : ElsaMongoDbContext + public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, IConfiguration configuration) where TDbContext : ElsaMongoDbContext { AddCore(elsa); elsa.Services.Configure(configuration); diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs new file mode 100644 index 000000000..6eef51f79 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs @@ -0,0 +1,31 @@ +using Elsa.Attributes; +using Elsa.Services.Startup; +using Elsa.Webhooks.Persistence.MongoDb.Extensions; +using Microsoft.Extensions.Configuration; + +namespace Elsa.Webhooks.Persistence.MongoDb +{ + [Feature("Webhooks:Persistence:MongoDb")] + public class Startup : StartupBase + { + public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) + { + var section = configuration.GetSection($"Elsa:Persistence:MongoDb"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); + + if (string.IsNullOrWhiteSpace(connectionString)) + { + if (string.IsNullOrWhiteSpace(connectionStringName)) + connectionStringName = "MongoDb"; + + connectionString = configuration.GetConnectionString(connectionStringName); + } + + if (string.IsNullOrWhiteSpace(connectionString)) + connectionString = "mongodb://localhost:27017/Elsa"; + + elsa.UseWebhookMongoDbPersistence(options => options.ConnectionString = connectionString); + } + } +} diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs index b17632c1f..a2da08481 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs @@ -1,21 +1,26 @@ using System; +using System.Data; using Elsa.Activities.Webhooks; using Elsa.Persistence.YesSql; +using Elsa.Persistence.YesSql.Data; +using Elsa.Persistence.YesSql.Mapping; +using Elsa.Persistence.YesSql.Services; +using Elsa.Runtime; +using Elsa.Webhooks.Persistence.YesSql.Indexes; using Elsa.Webhooks.Persistence.YesSql.Stores; using Microsoft.Extensions.DependencyInjection; using YesSql; using YesSql.Indexes; -using Elsa.Runtime; -using Elsa.Webhooks.Persistence.YesSql.Mapping; -using Elsa.Persistence.YesSql.Services; -using Elsa.Persistence.YesSql.Data; -using Elsa.Webhooks.Persistence.YesSql.Indexes; +using YesSql.Provider.Sqlite; namespace Elsa.Webhooks.Persistence.YesSql.Extensions { public static class WebhookServiceCollectionExtensions { - public static ElsaOptionsBuilder UseYesSqlPersistence(this ElsaOptionsBuilder elsa, Action configure) + public static ElsaOptionsBuilder UseWebhookYesSqlPersistence(this ElsaOptionsBuilder elsa) => elsa.UseWebhookYesSqlPersistence(config => config.UseSqLite("Data Source=elsa.yessql.db;Cache=Shared", IsolationLevel.ReadUncommitted)); + public static ElsaOptionsBuilder UseWebhookYesSqlPersistence(this ElsaOptionsBuilder elsa, Action configure) => elsa.UseWebhookYesSqlPersistence((_, config) => configure(config)); + + public static ElsaOptionsBuilder UseWebhookYesSqlPersistence(this ElsaOptionsBuilder elsa, Action configure) { elsa.Services .AddScoped() diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs new file mode 100644 index 000000000..bfa638599 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs @@ -0,0 +1,69 @@ +using System; +using Elsa.Attributes; +using Elsa.Services.Startup; +using Elsa.Webhooks.Persistence.YesSql.Extensions; +using Microsoft.Extensions.Configuration; +using YesSql.Provider.MySql; +using YesSql.Provider.PostgreSql; +using YesSql.Provider.Sqlite; +using YesSql.Provider.SqlServer; + +namespace Elsa.Webhooks.Persistence.YesSql +{ + [Feature("Webhooks:Persistence:YesSql:Sqlite")] + public class SqliteStartup : YesSqlStartupBase + { + protected override string ProviderName => "Sqlite"; + protected override string GetDefaultConnectionString() => "Data Source=elsa.yessql.db;Cache=Shared"; + protected override void Configure(global::YesSql.IConfiguration options, string connectionString) => options.UseSqLite(connectionString); + } + + [Feature("Webhooks:Persistence:YesSql:SqlServer")] + public class SqlServerStartup : YesSqlStartupBase + { + protected override string ProviderName => "SqlServer"; + protected override void Configure(global::YesSql.IConfiguration options, string connectionString) => options.UseSqlServer(connectionString); + } + + [Feature("Webhooks:Persistence:YesSql:MySql")] + public class MySqlStartup : YesSqlStartupBase + { + protected override string ProviderName => "MySql"; + protected override void Configure(global::YesSql.IConfiguration options, string connectionString) => options.UseMySql(connectionString); + } + + [Feature("Webhooks:Persistence:YesSql:PostgreSql")] + public class PostgreSqlStartup : YesSqlStartupBase + { + protected override string ProviderName => "PostgreSql"; + protected override void Configure(global::YesSql.IConfiguration options, string connectionString) => options.UsePostgreSql(connectionString); + } + + public abstract class YesSqlStartupBase : StartupBase + { + protected abstract string ProviderName { get; } + + public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) + { + var section = configuration.GetSection($"Elsa:Persistence:{ProviderName}"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); + + if (string.IsNullOrWhiteSpace(connectionString)) + { + if (string.IsNullOrWhiteSpace(connectionStringName)) + connectionStringName = ProviderName; + + connectionString = configuration.GetConnectionString(connectionStringName); + } + + if (string.IsNullOrWhiteSpace(connectionString)) + connectionString = GetDefaultConnectionString(); + + elsa.UseWebhookYesSqlPersistence(options => Configure(options, connectionString)); + } + + protected virtual string GetDefaultConnectionString() => throw new Exception($"No connection string specified for the {ProviderName} provider"); + protected abstract void Configure(global::YesSql.IConfiguration options, string connectionString); + } +} diff --git a/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj b/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj index 32b93819f..3d2644be1 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj +++ b/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj @@ -24,6 +24,10 @@ + + + + diff --git a/src/samples/server/Elsa.Samples.Server.Host/README.md b/src/samples/server/Elsa.Samples.Server.Host/README.md new file mode 100644 index 000000000..03d1e1f64 --- /dev/null +++ b/src/samples/server/Elsa.Samples.Server.Host/README.md @@ -0,0 +1,113 @@ +### Configure persistence in appsettings.json + +EF Sqlite +``` +"Elsa": { +"Features": [ + "Persistence:EntityFrameworkCore:Sqlite", + ... + ], +} +``` + +EF MySQL +``` +"Elsa": { +"Features": [ + "Persistence:EntityFrameworkCore:MySql", + ... + ], +} +``` + +EF SQL Server +``` +"Elsa": { +"Features": [ + "Persistence:EntityFrameworkCore:SqlServer", + ... + ], +} +``` + +EF Postgre +``` +"Elsa": { +"Features": [ + "Persistence:EntityFrameworkCore:PostgreSql", + ... + ], +} +``` + +EF MongoDB +``` +"Elsa": { +"Features": [ + "Persistence:MongoDb", + ... + ], +} +``` + +YesSql Sqlite +``` +"Elsa": { +"Features": [ + "Persistence:YesSql:Sqlite", + ... + ], +} +``` + +YesSql MySQL +``` +"Elsa": { +"Features": [ + "Persistence:YesSql:MySql", + ... + ], +} +``` + +YesSql SQL Server +``` +"Elsa": { +"Features": [ + "Persistence:YesSql:SqlServer", + ... + ], +} +``` + +YesSql Postgre +``` +"Elsa": { +"Features": [ + "Persistence:YesSql:PostgreSql", + ... + ], +} +``` + +### Configure connection strings for each persistence + +``` + "ConnectionStrings": { + ... + "MySql": "Server=LAPTOP-B76STK67;Database=Elsa;Uid=myUsername;Pwd=myPassword;", + "SqlServer": "Server=LAPTOP-B76STK67;Database=Elsa;Integrated Security=true;MultipleActiveResultSets=True;Max Pool Size=500;Connection Timeout=3600", + "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;", + "MongoDb": "mongodb://localhost:27017/Elsa" + }, +``` + +### Connection string examples +MySql +https://www.connectionstrings.com/mysql/ +SQL Server +https://www.connectionstrings.com/sql-server/ +Postgres +https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING +MongoDb +https://docs.mongodb.com/manual/reference/connection-string/ \ No newline at end of file diff --git a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs index 0b1043e78..6907a11c6 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs +++ b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs @@ -1,14 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Elsa.Activities.Conductor.Extensions; -using Elsa.Activities.Console; -using Elsa.Activities.Http; -using Elsa.Activities.UserTask.Extensions; -using Elsa.Persistence.EntityFramework.Core.Extensions; -using Elsa.Persistence.EntityFramework.Sqlite; -using Elsa.Providers.WorkflowStorage; using Elsa.Samples.Server.Host.Activities; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -41,7 +31,6 @@ namespace Elsa.Samples.Server.Host { typeof(Elsa.Activities.Console.Startup), typeof(Elsa.Activities.Http.Startup), - typeof(Elsa.Activities.Webhooks.Startup), typeof(Elsa.Activities.AzureServiceBus.Startup), typeof(Elsa.Activities.Conductor.Startup), typeof(Elsa.Activities.UserTask.Startup), @@ -58,6 +47,17 @@ namespace Elsa.Samples.Server.Host typeof(Persistence.YesSql.MySqlStartup), typeof(Persistence.YesSql.PostgreSqlStartup), typeof(Elsa.Scripting.JavaScript.Startup), + typeof(Elsa.Activities.Webhooks.Startup), + // Webhooks + typeof(Webhooks.Persistence.EntityFramework.Sqlite.Startup), + typeof(Webhooks.Persistence.EntityFramework.SqlServer.Startup), + typeof(Webhooks.Persistence.EntityFramework.MySql.Startup), + typeof(Webhooks.Persistence.EntityFramework.PostgreSql.Startup), + typeof(Webhooks.Persistence.MongoDb.Startup), + typeof(Webhooks.Persistence.YesSql.SqliteStartup), + typeof(Webhooks.Persistence.YesSql.SqlServerStartup), + typeof(Webhooks.Persistence.YesSql.MySqlStartup), + typeof(Webhooks.Persistence.YesSql.PostgreSqlStartup), }; services diff --git a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json index 3d302938b..700ab42e2 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json +++ b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json @@ -11,6 +11,7 @@ "ConnectionStrings": { "RabbitMq": "amqp://localhost:5672", "Redis": "localhost:6379,abortConnect=false", + "MySql": "Server=LAPTOP-B76STK67;Database=Elsa;Uid=myUsername;Pwd=myPassword;", "SqlServer": "Server=LAPTOP-B76STK67;Database=Elsa;Integrated Security=true;MultipleActiveResultSets=True;Max Pool Size=500;Connection Timeout=3600", "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;", "MongoDb": "mongodb://localhost:27017/Elsa" @@ -24,11 +25,22 @@ "Temporal:Quartz", "JavaScript:Activities", "UserTask", - "Conductor" + "Conductor", + "Webhooks", + "Webhooks:Persistence:EntityFrameworkCore:Sqlite" ], + "Persistence:MySql": { + "ConnectionStringName": "MySql" + }, + "Persistence:SqlServer": { + "ConnectionStringName": "SqlServer" + }, "Persistence:Sqlite": { "ConnectionStringName": "Sqlite" }, + "Persistence:MongoDb": { + "ConnectionStringName": "MongoDb" + }, "Http": { "BaseUrl": "https://localhost:11000", "BasePath": "/workflows" From e2ee25f56b807177221ebd906923f8a64bfec826 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Thu, 1 Jul 2021 10:43:58 +0300 Subject: [PATCH 02/10] Fix to Webhook update functionality Fix to Webhook update functionality --- .../Endpoints/WebhookDefinitions/Put.cs | 8 ++++---- .../elsa-webhook-definition-editor-screen.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Put.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Put.cs index cb26304ca..bdc60f57c 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Put.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Put.cs @@ -13,12 +13,12 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions { [ApiController] [ApiVersion("1")] - [Route("v{apiVersion:apiVersion}/webhook-definitions/{id}")] + [Route("v{apiVersion:apiVersion}/webhook-definitions")] [Produces("application/json")] - public class Put : ControllerBase + public class Update : ControllerBase { private readonly IWebhookDefinitionStore _store; - public Put(IWebhookDefinitionStore store) => _store = store; + public Update(IWebhookDefinitionStore store) => _store = store; [HttpPut] [ProducesResponseType(typeof(WebhookDefinition), StatusCodes.Status200OK)] @@ -44,7 +44,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions webhookDefinition.PayloadTypeName = request.PayloadTypeName?.Trim(); webhookDefinition.IsEnabled = request.IsEnabled; - await _store.SaveAsync(webhookDefinition, cancellationToken); + await _store.UpdateAsync(webhookDefinition, cancellationToken); return Ok(webhookDefinition); } diff --git a/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx index f99812138..d0290d3b0 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx @@ -94,7 +94,7 @@ export class ElsaWebhookDefinitionEditorScreen { this.saving = true; try { - + debugger if (request.id == null) webhookDefinition = await client.webhookDefinitionsApi.save(request); else From 130147f5c9950e4125c38b8ccd205d67ccacf8b2 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Fri, 2 Jul 2021 11:51:57 +0300 Subject: [PATCH 03/10] Work on YesSql persistence for Webhooks Work on YesSql persistence for Webhooks --- .../Endpoints/WebhookDefinitions/List.cs | 4 +-- .../EntityFrameworkWebhookStartupBase.cs | 2 +- .../WebhookServiceCollectionExtensions.cs | 12 +++---- .../Startups.cs | 16 +++++++++- .../server/Elsa.Samples.Server.Host/README.md | 31 ++++++++++++++++++- .../Elsa.Samples.Server.Host/appsettings.json | 6 ++-- 6 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/List.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/List.cs index 87fdf26d7..385fb42b0 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/List.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/List.cs @@ -3,11 +3,9 @@ using System.Net.Mime; using System.Threading; using System.Threading.Tasks; using Elsa.Activities.Webhooks.Swagger.Examples; -using Elsa.Models; using Elsa.Persistence.Specifications; using Elsa.Server.Api.Models; using Elsa.Server.Api.Services; -using Elsa.Server.Api.Swagger.Examples; using Elsa.Webhooks.Models; using Elsa.Webhooks.Persistence; using Microsoft.AspNetCore.Http; @@ -41,7 +39,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions OperationId = "WebhookDefinitions.List", Tags = new[] { "WebhookDefinitions" }) ] - public async Task>> Handle(CancellationToken cancellationToken = default) + public async Task>> Handle(CancellationToken cancellationToken = default) { var specification = Specification.Identity; var items = await _store.FindManyAsync(specification, cancellationToken: cancellationToken); diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs index cb2ae5b18..af5e3f21c 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs @@ -31,7 +31,7 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.Core if (string.IsNullOrWhiteSpace(connectionString)) connectionString = GetDefaultConnectionString(); - var webhookOptionsBuilder = new WebhookOptionsBuilder(elsa.Services); + var webhookOptionsBuilder = new WebhookOptionsBuilder(services); webhookOptionsBuilder.UseEntityFrameworkPersistence(options => Configure(options, connectionString)); services.AddScoped(sp => webhookOptionsBuilder.WebhookOptions.WebhookDefinitionStoreFactory(sp)); diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs index a2da08481..6c8b27ebb 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs @@ -17,12 +17,12 @@ namespace Elsa.Webhooks.Persistence.YesSql.Extensions { public static class WebhookServiceCollectionExtensions { - public static ElsaOptionsBuilder UseWebhookYesSqlPersistence(this ElsaOptionsBuilder elsa) => elsa.UseWebhookYesSqlPersistence(config => config.UseSqLite("Data Source=elsa.yessql.db;Cache=Shared", IsolationLevel.ReadUncommitted)); - public static ElsaOptionsBuilder UseWebhookYesSqlPersistence(this ElsaOptionsBuilder elsa, Action configure) => elsa.UseWebhookYesSqlPersistence((_, config) => configure(config)); + public static WebhookOptionsBuilder UseWebhookYesSqlPersistence(this WebhookOptionsBuilder webhookOptions) => webhookOptions.UseWebhookYesSqlPersistence(config => config.UseSqLite("Data Source=elsa.yessql.db;Cache=Shared", IsolationLevel.ReadUncommitted)); + public static WebhookOptionsBuilder UseWebhookYesSqlPersistence(this WebhookOptionsBuilder webhookOptions, Action configure) => webhookOptions.UseWebhookYesSqlPersistence((_, config) => configure(config)); - public static ElsaOptionsBuilder UseWebhookYesSqlPersistence(this ElsaOptionsBuilder elsa, Action configure) + public static WebhookOptionsBuilder UseWebhookYesSqlPersistence(this WebhookOptionsBuilder webhookOptions, Action configure) { - elsa.Services + webhookOptions.Services .AddScoped() .AddSingleton(sp => CreateStore(sp, configure)) .AddSingleton() @@ -34,11 +34,11 @@ namespace Elsa.Webhooks.Persistence.YesSql.Extensions .AddAutoMapperProfile() .AddIndexProvider(); - var webhookOptionsBuilder = new WebhookOptionsBuilder(elsa.Services); + var webhookOptionsBuilder = new WebhookOptionsBuilder(webhookOptions.Services); webhookOptionsBuilder.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); - return elsa; + return webhookOptions; } private static IStore CreateStore( diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs index bfa638599..7ad3f1235 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs @@ -1,8 +1,13 @@ using System; +using Elsa.Activities.Webhooks; +using Elsa.Activities.Webhooks.Persistence.Decorators; using Elsa.Attributes; using Elsa.Services.Startup; +//using Elsa.Webhooks.Persistence.EntityFramework.Core.Extensions; +//using Elsa.Webhooks.Persistence.YesSql.Extensions; using Elsa.Webhooks.Persistence.YesSql.Extensions; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using YesSql.Provider.MySql; using YesSql.Provider.PostgreSql; using YesSql.Provider.Sqlite; @@ -45,6 +50,7 @@ namespace Elsa.Webhooks.Persistence.YesSql public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) { + var services = elsa.Services; var section = configuration.GetSection($"Elsa:Persistence:{ProviderName}"); var connectionStringName = section.GetValue("ConnectionStringName"); var connectionString = section.GetValue("ConnectionString"); @@ -60,7 +66,15 @@ namespace Elsa.Webhooks.Persistence.YesSql if (string.IsNullOrWhiteSpace(connectionString)) connectionString = GetDefaultConnectionString(); - elsa.UseWebhookYesSqlPersistence(options => Configure(options, connectionString)); + //elsa.UseWebhookYesSqlPersistence(options => Configure(options, connectionString)); + + var webhookOptionsBuilder = new WebhookOptionsBuilder(services); + webhookOptionsBuilder.UseWebhookYesSqlPersistence(options => Configure(options, connectionString)); + + services.AddScoped(sp => webhookOptionsBuilder.WebhookOptions.WebhookDefinitionStoreFactory(sp)); + + services.Decorate(); + services.Decorate(); } protected virtual string GetDefaultConnectionString() => throw new Exception($"No connection string specified for the {ProviderName} provider"); diff --git a/src/samples/server/Elsa.Samples.Server.Host/README.md b/src/samples/server/Elsa.Samples.Server.Host/README.md index 03d1e1f64..b690a8e02 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/README.md +++ b/src/samples/server/Elsa.Samples.Server.Host/README.md @@ -90,6 +90,35 @@ YesSql Postgre } ``` +### Configure modular activity providers such as Webhooks +It is required to add modular activity provider and additional persistence feature for your modular activity provider. +The persistence providers should match for Elsa Core and modular activity providers. +Two examples below are given to set up Elsa Core and Webhooks persistence as follow. + +EF Sqlite +``` +"Elsa": { +"Features": [ + "Persistence:EntityFrameworkCore:Sqlite", + "Webhooks" + "Webhooks:Persistence:EntityFrameworkCore:Sqlite", + ... + ], +} +``` + +EF MongoDB +``` +"Elsa": { +"Features": [ + "Persistence:MongoDb", + "Webhooks" + "Webhooks:Persistence:MongoDb", + ... + ], +} +``` + ### Configure connection strings for each persistence ``` @@ -102,7 +131,7 @@ YesSql Postgre }, ``` -### Connection string examples +### Connection strings MySql https://www.connectionstrings.com/mysql/ SQL Server diff --git a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json index 700ab42e2..bb94da846 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json +++ b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json @@ -13,12 +13,12 @@ "Redis": "localhost:6379,abortConnect=false", "MySql": "Server=LAPTOP-B76STK67;Database=Elsa;Uid=myUsername;Pwd=myPassword;", "SqlServer": "Server=LAPTOP-B76STK67;Database=Elsa;Integrated Security=true;MultipleActiveResultSets=True;Max Pool Size=500;Connection Timeout=3600", - "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;", + "Sqlite": "Data Source=elsa.sqlite.yes.db;Cache=Shared;", "MongoDb": "mongodb://localhost:27017/Elsa" }, "Elsa": { "Features": [ - "Persistence:EntityFrameworkCore:Sqlite", + "Persistence:YesSql:Sqlite", "Console", "Http", "Email", @@ -27,7 +27,7 @@ "UserTask", "Conductor", "Webhooks", - "Webhooks:Persistence:EntityFrameworkCore:Sqlite" + "Webhooks:Persistence:YesSql:Sqlite" ], "Persistence:MySql": { "ConnectionStringName": "MySql" From 6feb8f4a7785d210819513f56d758cc9b35d88bf Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Fri, 2 Jul 2021 14:37:45 +0300 Subject: [PATCH 04/10] YesSQL persistence for Webhooks YesSQL persistence for Webhooks --- .../Documents/WebhookDefinitionDocument.cs | 2 +- .../Elsa.Webhooks.Persistence.YesSql.csproj | 2 +- .../WebhookServiceCollectionExtensions.cs | 29 ++++++++++++------- .../Indexes/WebhookDefinitionIndex.cs | 4 +-- .../Mapping/AutoMapperProfile.cs | 3 +- .../Migrations.cs | 2 +- .../Services/DatabaseInitializer.cs | 25 ++++++++++++++++ .../Stores/YesSqlWebhookDefinitionStore.cs | 5 ++-- .../Stores/YesSqlStore.cs | 4 +-- 9 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Services/DatabaseInitializer.cs diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs index 3f51036c7..e41525192 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs @@ -4,7 +4,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Documents { public class WebhookDefinitionDocument : YesSqlDocument { - public string WebhookDefinitionId { get; set; } = default!; + public string WebhookId { get; set; } = default!; public string? TenantId { get; set; } public string Name { get; set; } = default!; public string Path { get; set; } = default!; diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Elsa.Webhooks.Persistence.YesSql.csproj b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Elsa.Webhooks.Persistence.YesSql.csproj index 276cdc71e..51288f19c 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Elsa.Webhooks.Persistence.YesSql.csproj +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Elsa.Webhooks.Persistence.YesSql.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs index 6c8b27ebb..b5ef98cc6 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs @@ -1,10 +1,11 @@ using System; using System.Data; using Elsa.Activities.Webhooks; +using Elsa.Webhooks.Persistence.YesSql.Services; using Elsa.Persistence.YesSql; -using Elsa.Persistence.YesSql.Data; -using Elsa.Persistence.YesSql.Mapping; -using Elsa.Persistence.YesSql.Services; +//using Elsa.Persistence.YesSql.Data; +//using Elsa.Persistence.YesSql.Mapping; +//using Elsa.Persistence.YesSql.Services; using Elsa.Runtime; using Elsa.Webhooks.Persistence.YesSql.Indexes; using Elsa.Webhooks.Persistence.YesSql.Stores; @@ -12,6 +13,8 @@ using Microsoft.Extensions.DependencyInjection; using YesSql; using YesSql.Indexes; using YesSql.Provider.Sqlite; +using Elsa.Persistence.YesSql.Data; +using Elsa.Webhooks.Persistence.YesSql.Mapping; namespace Elsa.Webhooks.Persistence.YesSql.Extensions { @@ -25,22 +28,28 @@ namespace Elsa.Webhooks.Persistence.YesSql.Extensions webhookOptions.Services .AddScoped() .AddSingleton(sp => CreateStore(sp, configure)) - .AddSingleton() - .AddScoped(CreateSession) - .AddScoped() + //.AddSingleton() + //.AddScoped(CreateSession) + //.AddScoped() .AddStartupTask() - .AddStartupTask() + //.AddStartupTask() .AddDataMigration() .AddAutoMapperProfile() .AddIndexProvider(); - var webhookOptionsBuilder = new WebhookOptionsBuilder(webhookOptions.Services); + //var webhookOptionsBuilder = new WebhookOptionsBuilder(webhookOptions.Services); - webhookOptionsBuilder.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); + + webhookOptions.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); return webhookOptions; } + public static IServiceCollection AddIndexProvider(this IServiceCollection services) where T : class, IIndexProvider => services.AddSingleton(); + public static IServiceCollection AddScopedIndexProvider(this IServiceCollection services) where T : class, IIndexProvider => services.AddScoped(); + + public static IServiceCollection AddDataMigration(this IServiceCollection services) where T : class, IDataMigration => services.AddScoped(); + private static IStore CreateStore( IServiceProvider serviceProvider, Action configure) @@ -64,7 +73,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Extensions private static ISession CreateSession(IServiceProvider serviceProvider) { - var provider = serviceProvider.GetRequiredService(); + var provider = serviceProvider.GetRequiredService(); return provider.CreateSession(); } } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs index 3c9ae4194..e1f7bb7bd 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs @@ -6,7 +6,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Indexes { public class WebhookDefinitionIndex : MapIndex { - public string WebhookDefinitionId { get; set; } = default!; + public string WebhookId { get; set; } = default!; public string? TenantId { get; set; } public bool IsEnabled { get; set; } } @@ -21,7 +21,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Indexes .Map( webhookDefinition => new WebhookDefinitionIndex { - WebhookDefinitionId = webhookDefinition.WebhookDefinitionId, + WebhookId = webhookDefinition.WebhookId, TenantId = webhookDefinition.TenantId, IsEnabled = webhookDefinition.IsEnabled } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs index 86f3b1dad..b5eaa8c7f 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs @@ -9,9 +9,10 @@ namespace Elsa.Webhooks.Persistence.YesSql.Mapping public AutoMapperProfile() { CreateMap() + .ForMember(d => d.WebhookId, d => d.MapFrom(s => s.Id)) .ForMember(d => d.Id, d => d.Ignore()) .ReverseMap() - .ForMember(d => d.Id, d => d.MapFrom(s => s.Id)); + .ForMember(d => d.Id, d => d.MapFrom(s => s.WebhookId)); } } } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs index 7a76e8f6c..6048b50dc 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs @@ -11,7 +11,7 @@ namespace Elsa.Webhooks.Persistence.YesSql { SchemaBuilder.CreateMapIndexTable( table => table - .Column(nameof(WebhookDefinitionIndex.WebhookDefinitionId)) + .Column(nameof(WebhookDefinitionIndex.WebhookId)) .Column(nameof(WebhookDefinitionIndex.TenantId)) .Column(nameof(WebhookDefinitionIndex.IsEnabled)), CollectionNames.WebhookDefinitions); diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Services/DatabaseInitializer.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Services/DatabaseInitializer.cs new file mode 100644 index 000000000..cc9a3e3b2 --- /dev/null +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Services/DatabaseInitializer.cs @@ -0,0 +1,25 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Services; +using Elsa.Webhooks.Persistence.YesSql.Data; +using YesSql; + +namespace Elsa.Webhooks.Persistence.YesSql.Services +{ + public class DatabaseInitializer : IStartupTask + { + private readonly IStore _store; + + public DatabaseInitializer(IStore store) + { + _store = store; + } + + public int Order => 0; + + public async Task ExecuteAsync(CancellationToken cancellationToken = default) + { + await _store.InitializeCollectionAsync(CollectionNames.WebhookDefinitions); + } + } +} diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs index 497977e51..4156ee52f 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs @@ -1,6 +1,5 @@ using System.Threading; using System.Threading.Tasks; -using Elsa.Models; using Elsa.Webhooks.Persistence.YesSql.Data; using Elsa.Webhooks.Persistence.YesSql.Documents; using Elsa.Webhooks.Persistence.YesSql.Indexes; @@ -22,13 +21,13 @@ namespace Elsa.Webhooks.Persistence.YesSql.Stores { } - protected override async Task FindDocumentAsync(ISession session, WebhookDefinition entity, CancellationToken cancellationToken) => await Query(session, x => x.WebhookDefinitionId == entity.Id).FirstOrDefaultAsync(); + protected override async Task FindDocumentAsync(ISession session, WebhookDefinition entity, CancellationToken cancellationToken) => await Query(session, x => x.WebhookId == entity.Id).FirstOrDefaultAsync(); protected override IQuery MapSpecification(ISession session, ISpecification specification) { return specification switch { - EntityIdSpecification s => Query(session, x => x.WebhookDefinitionId == s.Id), + EntityIdSpecification s => Query(session, x => x.WebhookId == s.Id), _ => AutoMapSpecification(session, specification) }; } diff --git a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs index 6115ef924..36d91b078 100644 --- a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs +++ b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs @@ -41,14 +41,14 @@ namespace Elsa.Persistence.YesSql.Stores { await _semaphore.WaitAsync(cancellationToken); - try + try { await using var session = SessionProvider.CreateSession(); var existingDocument = await FindDocumentAsync(session, entity, cancellationToken); var document = Mapper.Map(entity, existingDocument); session.Save(document, CollectionName); await session.SaveChangesAsync(); - } + } finally { _semaphore.Release(); From d8ab9070af467277228c75da3a0af41c76695b87 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Fri, 2 Jul 2021 16:24:17 +0300 Subject: [PATCH 05/10] MongoDB persistence fixed for Webhooks MongoDB persistence fixed for Webhooks --- .../Endpoints/WebhookDefinitions/Post.cs | 2 +- .../WebhookServiceCollectionExtensions.cs | 28 +++++++++---------- .../Services/DatabaseInitializer.cs | 18 +++++++++--- .../Startup.cs | 12 +++++++- .../WebhookServiceCollectionExtensions.cs | 10 ------- .../Startups.cs | 7 +---- .../Elsa.Samples.Server.Host/appsettings.json | 4 +-- 7 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs index 2bccae227..92a89aea6 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs @@ -46,7 +46,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions webhookDefinition = new WebhookDefinition { Id = !string.IsNullOrWhiteSpace(webhookId) ? webhookId : _idGenerator.Generate(), - }; + }; webhookDefinition.Name = request.Name.Trim(); webhookDefinition.Path = request.Path.Trim(); diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs index 07fcd14cd..0f698b571 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Extensions/WebhookServiceCollectionExtensions.cs @@ -11,37 +11,35 @@ namespace Elsa.Webhooks.Persistence.MongoDb.Extensions { public static class WebhookServiceCollectionExtensions { - public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, Action configureOptions) => UseWebhookMongoDbPersistence(elsa, configureOptions); + public static WebhookOptionsBuilder UseWebhookMongoDbPersistence(this WebhookOptionsBuilder webhookOptions, Action configureOptions) => UseWebhookMongoDbPersistence(webhookOptions, configureOptions); - public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, Action configureOptions) where TDbContext : ElsaMongoDbContext + public static WebhookOptionsBuilder UseWebhookMongoDbPersistence(this WebhookOptionsBuilder webhookOptions, Action configureOptions) where TDbContext : ElsaMongoDbContext { - AddCore(elsa); - elsa.Services.Configure(configureOptions); + AddCore(webhookOptions); + webhookOptions.Services.Configure(configureOptions); - return elsa; + return webhookOptions; } - public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, IConfiguration configuration) => UseWebhookMongoDbPersistence(elsa, configuration); + public static WebhookOptionsBuilder UseWebhookMongoDbPersistence(this WebhookOptionsBuilder webhookOptions, IConfiguration configuration) => UseWebhookMongoDbPersistence(webhookOptions, configuration); - public static ElsaOptionsBuilder UseWebhookMongoDbPersistence(this ElsaOptionsBuilder elsa, IConfiguration configuration) where TDbContext : ElsaMongoDbContext + public static WebhookOptionsBuilder UseWebhookMongoDbPersistence(this WebhookOptionsBuilder webhookOptions, IConfiguration configuration) where TDbContext : ElsaMongoDbContext { - AddCore(elsa); - elsa.Services.Configure(configuration); - return elsa; + AddCore(webhookOptions); + webhookOptions.Services.Configure(configuration); + return webhookOptions; } - private static void AddCore(ElsaOptionsBuilder elsa) where TDbContext : ElsaMongoDbContext + private static void AddCore(WebhookOptionsBuilder webhookOptions) where TDbContext : ElsaMongoDbContext { - elsa.Services + webhookOptions.Services .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton(sp => sp.GetRequiredService().WebhookDefinitions) .AddStartupTask(); - var webhookOptionsBuilder = new WebhookOptionsBuilder(elsa.Services); - - webhookOptionsBuilder.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); + webhookOptions.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); DatabaseRegister.RegisterMapsAndSerializers(); } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs index a9f136291..39af5f3c6 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs @@ -25,13 +25,23 @@ namespace Elsa.Webhooks.Persistence.MongoDb.Services private async Task CreateWebhookDefinitionsIndexes(CancellationToken cancellationToken) { + //var builder = Builders.IndexKeys; + //var tenantKeysDefinition = builder.Ascending(x => x.TenantId); + //var nameKeysDefinition = builder.Ascending(x => x.Name); + //var webhookIdDefinition = builder.Ascending(x => x.Id); + //var collection = _mongoContext.WebhookDefinitions; + //await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, webhookIdDefinition, nameKeysDefinition); + //await collection.Indexes.CreateOneAsync(new CreateIndexModel(webhookIdDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken); + var builder = Builders.IndexKeys; var tenantKeysDefinition = builder.Ascending(x => x.TenantId); var nameKeysDefinition = builder.Ascending(x => x.Name); - var webhookIdDefinition = builder.Ascending(x => x.Id); - var collection = _mongoContext.WebhookDefinitions; - await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, webhookIdDefinition, nameKeysDefinition); - await collection.Indexes.CreateOneAsync(new CreateIndexModel(webhookIdDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken); + var pathKeysDefinition = builder.Ascending(x => x.Path); + var payloadKeysDefinition = builder.Ascending(x => x.PayloadTypeName); + //var webhookDefinitionIdAndVersionKeyDefinition = builder.Combine(builder.Ascending(x => x.DefinitionId), builder.Ascending(x => x.Version)); + //var collection = _mongoContext.WebhookDefinitions; + await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, nameKeysDefinition, pathKeysDefinition, payloadKeysDefinition); + //await collection.Indexes.CreateOneAsync(new CreateIndexModel(workflowDefinitionIdAndVersionKeyDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken); } private async Task CreateIndexesAsync(IMongoCollection collection, CancellationToken cancellationToken, params IndexKeysDefinition[] definitions) diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs index 6eef51f79..c8295b9dd 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs @@ -1,7 +1,11 @@ +using Elsa.Activities.Webhooks; +using Elsa.Activities.Webhooks.Persistence.Decorators; using Elsa.Attributes; +using Elsa.Persistence.MongoDb.Options; using Elsa.Services.Startup; using Elsa.Webhooks.Persistence.MongoDb.Extensions; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.Webhooks.Persistence.MongoDb { @@ -10,6 +14,7 @@ namespace Elsa.Webhooks.Persistence.MongoDb { public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) { + var services = elsa.Services; var section = configuration.GetSection($"Elsa:Persistence:MongoDb"); var connectionStringName = section.GetValue("ConnectionStringName"); var connectionString = section.GetValue("ConnectionString"); @@ -25,7 +30,12 @@ namespace Elsa.Webhooks.Persistence.MongoDb if (string.IsNullOrWhiteSpace(connectionString)) connectionString = "mongodb://localhost:27017/Elsa"; - elsa.UseWebhookMongoDbPersistence(options => options.ConnectionString = connectionString); + var webhookOptionsBuilder = new WebhookOptionsBuilder(services); + webhookOptionsBuilder.UseWebhookMongoDbPersistence(options => options.ConnectionString = connectionString); + + services.AddScoped(sp => webhookOptionsBuilder.WebhookOptions.WebhookDefinitionStoreFactory(sp)); + services.Decorate(); + services.Decorate(); } } } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs index b5ef98cc6..c1e5bdfd5 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Extensions/WebhookServiceCollectionExtensions.cs @@ -3,9 +3,6 @@ using System.Data; using Elsa.Activities.Webhooks; using Elsa.Webhooks.Persistence.YesSql.Services; using Elsa.Persistence.YesSql; -//using Elsa.Persistence.YesSql.Data; -//using Elsa.Persistence.YesSql.Mapping; -//using Elsa.Persistence.YesSql.Services; using Elsa.Runtime; using Elsa.Webhooks.Persistence.YesSql.Indexes; using Elsa.Webhooks.Persistence.YesSql.Stores; @@ -28,18 +25,11 @@ namespace Elsa.Webhooks.Persistence.YesSql.Extensions webhookOptions.Services .AddScoped() .AddSingleton(sp => CreateStore(sp, configure)) - //.AddSingleton() - //.AddScoped(CreateSession) - //.AddScoped() .AddStartupTask() - //.AddStartupTask() .AddDataMigration() .AddAutoMapperProfile() .AddIndexProvider(); - //var webhookOptionsBuilder = new WebhookOptionsBuilder(webhookOptions.Services); - - webhookOptions.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); return webhookOptions; diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs index 7ad3f1235..51081f3cf 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs @@ -3,8 +3,6 @@ using Elsa.Activities.Webhooks; using Elsa.Activities.Webhooks.Persistence.Decorators; using Elsa.Attributes; using Elsa.Services.Startup; -//using Elsa.Webhooks.Persistence.EntityFramework.Core.Extensions; -//using Elsa.Webhooks.Persistence.YesSql.Extensions; using Elsa.Webhooks.Persistence.YesSql.Extensions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -65,14 +63,11 @@ namespace Elsa.Webhooks.Persistence.YesSql if (string.IsNullOrWhiteSpace(connectionString)) connectionString = GetDefaultConnectionString(); - - //elsa.UseWebhookYesSqlPersistence(options => Configure(options, connectionString)); - + var webhookOptionsBuilder = new WebhookOptionsBuilder(services); webhookOptionsBuilder.UseWebhookYesSqlPersistence(options => Configure(options, connectionString)); services.AddScoped(sp => webhookOptionsBuilder.WebhookOptions.WebhookDefinitionStoreFactory(sp)); - services.Decorate(); services.Decorate(); } diff --git a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json index bb94da846..3ddfcb803 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json +++ b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json @@ -18,7 +18,7 @@ }, "Elsa": { "Features": [ - "Persistence:YesSql:Sqlite", + "Persistence:MongoDb", "Console", "Http", "Email", @@ -27,7 +27,7 @@ "UserTask", "Conductor", "Webhooks", - "Webhooks:Persistence:YesSql:Sqlite" + "Webhooks:Persistence:MongoDb" ], "Persistence:MySql": { "ConnectionStringName": "MySql" From 517b22dab63904257108d3d0bcc2fd73ffdbb417 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Fri, 2 Jul 2021 16:58:54 +0300 Subject: [PATCH 06/10] Clean up and restored the persistence in appsettings to EF Sqlite Clean up and restored the persistence in appsettings to EF Sqlite --- src/samples/server/Elsa.Samples.Server.Host/README.md | 3 ++- .../server/Elsa.Samples.Server.Host/appsettings.json | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/samples/server/Elsa.Samples.Server.Host/README.md b/src/samples/server/Elsa.Samples.Server.Host/README.md index b690a8e02..683a5f2a2 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/README.md +++ b/src/samples/server/Elsa.Samples.Server.Host/README.md @@ -127,7 +127,8 @@ EF MongoDB "MySql": "Server=LAPTOP-B76STK67;Database=Elsa;Uid=myUsername;Pwd=myPassword;", "SqlServer": "Server=LAPTOP-B76STK67;Database=Elsa;Integrated Security=true;MultipleActiveResultSets=True;Max Pool Size=500;Connection Timeout=3600", "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;", - "MongoDb": "mongodb://localhost:27017/Elsa" + "MongoDb": "mongodb://localhost:27017/Elsa", + "PostgreSql": "Server=127.0.0.1;Port=5432;Database=elsa;User Id=postgres;Password=password;" }, ``` diff --git a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json index 3ddfcb803..85a9b0d7f 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json +++ b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json @@ -14,11 +14,12 @@ "MySql": "Server=LAPTOP-B76STK67;Database=Elsa;Uid=myUsername;Pwd=myPassword;", "SqlServer": "Server=LAPTOP-B76STK67;Database=Elsa;Integrated Security=true;MultipleActiveResultSets=True;Max Pool Size=500;Connection Timeout=3600", "Sqlite": "Data Source=elsa.sqlite.yes.db;Cache=Shared;", - "MongoDb": "mongodb://localhost:27017/Elsa" + "MongoDb": "mongodb://localhost:27017/Elsa", + "PostgreSql": "Server=127.0.0.1;Port=5432;Database=elsa;User Id=postgres;Password=password;" }, "Elsa": { "Features": [ - "Persistence:MongoDb", + "Persistence:EntityFrameworkCore:Sqlite", "Console", "Http", "Email", @@ -27,7 +28,7 @@ "UserTask", "Conductor", "Webhooks", - "Webhooks:Persistence:MongoDb" + "Webhooks:Persistence:EntityFrameworkCore:Sqlite" ], "Persistence:MySql": { "ConnectionStringName": "MySql" @@ -41,6 +42,9 @@ "Persistence:MongoDb": { "ConnectionStringName": "MongoDb" }, + "Persistence:PostgreSql": { + "ConnectionStringName": "PostgreSql" + }, "Http": { "BaseUrl": "https://localhost:11000", "BasePath": "/workflows" From 19b5868d086305ca8250e2464505e04d95e3c701 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Fri, 2 Jul 2021 21:31:39 +0300 Subject: [PATCH 07/10] Readme update Readme update --- src/samples/server/Elsa.Samples.Server.Host/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samples/server/Elsa.Samples.Server.Host/README.md b/src/samples/server/Elsa.Samples.Server.Host/README.md index 683a5f2a2..ea7b451d1 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/README.md +++ b/src/samples/server/Elsa.Samples.Server.Host/README.md @@ -128,7 +128,7 @@ EF MongoDB "SqlServer": "Server=LAPTOP-B76STK67;Database=Elsa;Integrated Security=true;MultipleActiveResultSets=True;Max Pool Size=500;Connection Timeout=3600", "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;", "MongoDb": "mongodb://localhost:27017/Elsa", - "PostgreSql": "Server=127.0.0.1;Port=5432;Database=elsa;User Id=postgres;Password=password;" + "PostgreSql": "Server=127.0.0.1;Port=5433;Database=elsa;User Id=postgres;Password=Password12!;" }, ``` From 57b587f62103305a40dff882d1121f9c253b00f4 Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Mon, 5 Jul 2021 10:25:27 +0300 Subject: [PATCH 08/10] Clean up based on code review Clean up based on code review --- .../Endpoints/WebhookDefinitions/Post.cs | 2 +- .../WebhookServiceCollectionExtensions.cs | 229 ------------------ .../Services/DatabaseInitializer.cs | 11 - .../Documents/WebhookDefinitionDocument.cs | 2 +- .../Indexes/WebhookDefinitionIndex.cs | 4 +- .../Mapping/AutoMapperProfile.cs | 4 +- .../Migrations.cs | 2 +- .../Stores/YesSqlWebhookDefinitionStore.cs | 4 +- .../elsa-webhook-definition-editor-screen.tsx | 1 - .../Stores/YesSqlStore.cs | 2 +- .../Elsa.Samples.Server.Host/Startup.cs | 1 - 11 files changed, 10 insertions(+), 252 deletions(-) delete mode 100644 src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookServiceCollectionExtensions.cs diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs index 92a89aea6..2bccae227 100644 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs +++ b/src/activities/webhooks/Elsa.Activities.Webhooks/Endpoints/WebhookDefinitions/Post.cs @@ -46,7 +46,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions webhookDefinition = new WebhookDefinition { Id = !string.IsNullOrWhiteSpace(webhookId) ? webhookId : _idGenerator.Generate(), - }; + }; webhookDefinition.Name = request.Name.Trim(); webhookDefinition.Path = request.Path.Trim(); diff --git a/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookServiceCollectionExtensions.cs b/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookServiceCollectionExtensions.cs deleted file mode 100644 index 3266059f4..000000000 --- a/src/activities/webhooks/Elsa.Activities.Webhooks/Extensions/WebhookServiceCollectionExtensions.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using Elsa.Persistence.EntityFramework.Core; -using Elsa.Runtime; -using Elsa.Webhooks.Persistence.EntityFramework.Core; -using Elsa.Webhooks.Persistence.EntityFramework.Core.Services; -using Elsa.Webhooks.Persistence.EntityFramework.Core.StartupTasks; -using Elsa.Webhooks.Persistence.EntityFramework.Core.Stores; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; - -namespace Elsa.Activities.Webhooks.Extensions -{ - public static class WebhookServiceCollectionExtensions - { - /// - /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. - /// - /// - /// - /// Pooled DB Context instances is a performance optimisation which is documented in more detail at - /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. - /// - /// - /// An Elsa options builder - /// A configuration builder callback - /// If true then database migrations will be auto-executed on startup - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - bool autoRunMigrations = true) => - webhookOptions.UseEntityFrameworkPersistence(configure, autoRunMigrations); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. - /// - /// - /// - /// Pooled DB Context instances is a performance optimisation which is documented in more detail at - /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. - /// - /// - /// An Elsa options builder - /// A configuration builder callback - /// If true then database migrations will be auto-executed on startup - /// The concrete type of to use. - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - bool autoRunMigrations = true) where TWebhookContext : WebhookContext => - webhookOptions.UseEntityFrameworkPersistence((_, builder) => configure(builder), autoRunMigrations); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. - /// - /// - /// - /// Pooled DB Context instances is a performance optimisation which is documented in more detail at - /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. - /// - /// - /// An Elsa options builder - /// A configuration builder callback, which also provides access to a service provider - /// If true then database migrations will be auto-executed on startup - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - bool autoRunMigrations = true) => - webhookOptions.UseEntityFrameworkPersistence(configure, autoRunMigrations); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, using pooled DB Context instances. - /// - /// - /// - /// Pooled DB Context instances is a performance optimisation which is documented in more detail at - /// https://docs.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-constant#dbcontext-pooling. - /// - /// - /// An Elsa options builder - /// A configuration builder callback, which also provides access to a service provider - /// If true then database migrations will be auto-executed on startup - /// The concrete type of to use. - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - bool autoRunMigrations = true) where TWebhookContext : WebhookContext => - UseEntityFrameworkPersistence(webhookOptions, configure, autoRunMigrations, true, ServiceLifetime.Singleton); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. - /// - /// - /// - /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant - /// application, where re-use of DB Context objects is impractical. - /// - /// - /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of - /// the DB Context may differ, it is not feasible to try to automatically migrate them. - /// Your application is ultimately responsible for executing the contents of the class in a manner - /// which is suitable for your use-case. - /// - /// - /// An Elsa options builder - /// A configuration builder callback - /// The service lifetime which will be used for each DB Context instance - /// If true then database migrations will be auto-executed on startup - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, - bool autoRunMigrations = false) => - webhookOptions.UseNonPooledEntityFrameworkPersistence(configure, serviceLifetime, autoRunMigrations); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. - /// - /// - /// - /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant - /// application, where re-use of DB Context objects is impractical. - /// - /// - /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of - /// the DB Context may differ, it is not feasible to try to automatically migrate them. - /// Your application is ultimately responsible for executing the contents of the class in a manner - /// which is suitable for your use-case. - /// - /// - /// An Elsa options builder - /// A configuration builder callback - /// The service lifetime which will be used for each DB Context instance - /// If true then database migrations will be auto-executed on startup - /// The concrete type of to use. - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, - bool autoRunMigrations = false) where TWebhookContext : WebhookContext => - webhookOptions.UseNonPooledEntityFrameworkPersistence((_, builder) => configure(builder), serviceLifetime, autoRunMigrations); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. - /// - /// - /// - /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant - /// application, where re-use of DB Context objects is impractical. - /// - /// - /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of - /// the DB Context may differ, it is not feasible to try to automatically migrate them. - /// Your application is ultimately responsible for executing the contents of the class in a manner - /// which is suitable for your use-case. - /// - /// - /// An Elsa options builder - /// A configuration builder callback, which also provides access to a service provider - /// The service lifetime which will be used for each DB Context instance - /// If true then database migrations will be auto-executed on startup - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, - bool autoRunMigrations = false) => - webhookOptions.UseNonPooledEntityFrameworkPersistence(configure, serviceLifetime, autoRunMigrations); - - /// - /// Configures Elsa to use Entity Framework Core for persistence, without using pooled DB Context instances. - /// - /// - /// - /// Use this method when you do not wish to use DB connection pooling, such as when integrating with a multi-tenant - /// application, where re-use of DB Context objects is impractical. - /// - /// - /// Although auto-running of migrations is supported in this scenario, use this with caution. When pooling is not in use and each instance of - /// the DB Context may differ, it is not feasible to try to automatically migrate them. - /// Your application is ultimately responsible for executing the contents of the class in a manner - /// which is suitable for your use-case. - /// - /// - /// An Elsa options builder - /// A configuration builder callback, which also provides access to a service provider - /// The service lifetime which will be used for each DB Context instance - /// If true then database migrations will be auto-executed on startup - /// The concrete type of to use. - /// The Elsa options builder, so calls may be chained - public static WebhookOptionsBuilder UseNonPooledEntityFrameworkPersistence(this WebhookOptionsBuilder webhookOptions, - Action configure, - ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, - bool autoRunMigrations = false) where TWebhookContext : WebhookContext => - UseEntityFrameworkPersistence(webhookOptions, configure, autoRunMigrations, false, serviceLifetime); - - static WebhookOptionsBuilder UseEntityFrameworkPersistence(WebhookOptionsBuilder webhookOptions, - Action configure, - bool autoRunMigrations, - bool useContextPooling, - ServiceLifetime serviceLifetime) where TWebhookContext : WebhookContext - { - /* Auto-running migrations is intentionally unavailable when not using context pooling. - * When we aren't using pooling then it probably means that each DB Context is different - * in some manner. That could easily mean the connection strings (IE: Contexts might not - * all connect to the same DB). In that case, without further logic (which can't be - * pre-empted by Elsa), we can't be sure we're connecting to the right DBs when running - * migrations. - * - * It's much more sane just to explicitly not-support it and leave it to the app developer. - * They can run their own migrations in line with their own logic. - */ - - if (useContextPooling) - webhookOptions.Services.AddPooledDbContextFactory(configure); - else - webhookOptions.Services.AddDbContextFactory(configure, serviceLifetime); - - webhookOptions.Services - .AddSingleton>() - .AddScoped(); - - if (autoRunMigrations) - webhookOptions.Services.AddStartupTask(); - - webhookOptions.UseWebhookDefinitionStore(sp => sp.GetRequiredService()); - - return webhookOptions; - } - } -} diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs index 39af5f3c6..212f522fe 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Services/DatabaseInitializer.cs @@ -25,23 +25,12 @@ namespace Elsa.Webhooks.Persistence.MongoDb.Services private async Task CreateWebhookDefinitionsIndexes(CancellationToken cancellationToken) { - //var builder = Builders.IndexKeys; - //var tenantKeysDefinition = builder.Ascending(x => x.TenantId); - //var nameKeysDefinition = builder.Ascending(x => x.Name); - //var webhookIdDefinition = builder.Ascending(x => x.Id); - //var collection = _mongoContext.WebhookDefinitions; - //await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, webhookIdDefinition, nameKeysDefinition); - //await collection.Indexes.CreateOneAsync(new CreateIndexModel(webhookIdDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken); - var builder = Builders.IndexKeys; var tenantKeysDefinition = builder.Ascending(x => x.TenantId); var nameKeysDefinition = builder.Ascending(x => x.Name); var pathKeysDefinition = builder.Ascending(x => x.Path); var payloadKeysDefinition = builder.Ascending(x => x.PayloadTypeName); - //var webhookDefinitionIdAndVersionKeyDefinition = builder.Combine(builder.Ascending(x => x.DefinitionId), builder.Ascending(x => x.Version)); - //var collection = _mongoContext.WebhookDefinitions; await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, nameKeysDefinition, pathKeysDefinition, payloadKeysDefinition); - //await collection.Indexes.CreateOneAsync(new CreateIndexModel(workflowDefinitionIdAndVersionKeyDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken); } private async Task CreateIndexesAsync(IMongoCollection collection, CancellationToken cancellationToken, params IndexKeysDefinition[] definitions) diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs index e41525192..77d19a1ed 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Documents/WebhookDefinitionDocument.cs @@ -4,7 +4,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Documents { public class WebhookDefinitionDocument : YesSqlDocument { - public string WebhookId { get; set; } = default!; + public string DefinitionId { get; set; } = default!; public string? TenantId { get; set; } public string Name { get; set; } = default!; public string Path { get; set; } = default!; diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs index e1f7bb7bd..9897ee541 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Indexes/WebhookDefinitionIndex.cs @@ -6,7 +6,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Indexes { public class WebhookDefinitionIndex : MapIndex { - public string WebhookId { get; set; } = default!; + public string DefinitionId { get; set; } = default!; public string? TenantId { get; set; } public bool IsEnabled { get; set; } } @@ -21,7 +21,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Indexes .Map( webhookDefinition => new WebhookDefinitionIndex { - WebhookId = webhookDefinition.WebhookId, + DefinitionId = webhookDefinition.DefinitionId, TenantId = webhookDefinition.TenantId, IsEnabled = webhookDefinition.IsEnabled } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs index b5eaa8c7f..59811bb2b 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Mapping/AutoMapperProfile.cs @@ -9,10 +9,10 @@ namespace Elsa.Webhooks.Persistence.YesSql.Mapping public AutoMapperProfile() { CreateMap() - .ForMember(d => d.WebhookId, d => d.MapFrom(s => s.Id)) + .ForMember(d => d.DefinitionId, d => d.MapFrom(s => s.Id)) .ForMember(d => d.Id, d => d.Ignore()) .ReverseMap() - .ForMember(d => d.Id, d => d.MapFrom(s => s.WebhookId)); + .ForMember(d => d.Id, d => d.MapFrom(s => s.DefinitionId)); } } } diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs index 6048b50dc..b645192ff 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs @@ -11,7 +11,7 @@ namespace Elsa.Webhooks.Persistence.YesSql { SchemaBuilder.CreateMapIndexTable( table => table - .Column(nameof(WebhookDefinitionIndex.WebhookId)) + .Column(nameof(WebhookDefinitionIndex.DefinitionId)) .Column(nameof(WebhookDefinitionIndex.TenantId)) .Column(nameof(WebhookDefinitionIndex.IsEnabled)), CollectionNames.WebhookDefinitions); diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs index 4156ee52f..6d6cfbb78 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Stores/YesSqlWebhookDefinitionStore.cs @@ -21,13 +21,13 @@ namespace Elsa.Webhooks.Persistence.YesSql.Stores { } - protected override async Task FindDocumentAsync(ISession session, WebhookDefinition entity, CancellationToken cancellationToken) => await Query(session, x => x.WebhookId == entity.Id).FirstOrDefaultAsync(); + protected override async Task FindDocumentAsync(ISession session, WebhookDefinition entity, CancellationToken cancellationToken) => await Query(session, x => x.DefinitionId == entity.Id).FirstOrDefaultAsync(); protected override IQuery MapSpecification(ISession session, ISpecification specification) { return specification switch { - EntityIdSpecification s => Query(session, x => x.WebhookId == s.Id), + EntityIdSpecification s => Query(session, x => x.DefinitionId == s.Id), _ => AutoMapSpecification(session, specification) }; } diff --git a/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx index d0290d3b0..e912d2cb5 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/webhook-definition-editor/elsa-webhook-definition-editor-screen/elsa-webhook-definition-editor-screen.tsx @@ -94,7 +94,6 @@ export class ElsaWebhookDefinitionEditorScreen { this.saving = true; try { - debugger if (request.id == null) webhookDefinition = await client.webhookDefinitionsApi.save(request); else diff --git a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs index 36d91b078..17f8ad430 100644 --- a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs +++ b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs @@ -41,7 +41,7 @@ namespace Elsa.Persistence.YesSql.Stores { await _semaphore.WaitAsync(cancellationToken); - try + try { await using var session = SessionProvider.CreateSession(); var existingDocument = await FindDocumentAsync(session, entity, cancellationToken); diff --git a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs index 6907a11c6..649fbb954 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs +++ b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs @@ -48,7 +48,6 @@ namespace Elsa.Samples.Server.Host typeof(Persistence.YesSql.PostgreSqlStartup), typeof(Elsa.Scripting.JavaScript.Startup), typeof(Elsa.Activities.Webhooks.Startup), - // Webhooks typeof(Webhooks.Persistence.EntityFramework.Sqlite.Startup), typeof(Webhooks.Persistence.EntityFramework.SqlServer.Startup), typeof(Webhooks.Persistence.EntityFramework.MySql.Startup), From 1a61da8be6d337ad801d2d65d2f237c3f668176d Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Mon, 5 Jul 2021 11:42:00 +0300 Subject: [PATCH 09/10] whitespace removal whitespace removal --- src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs index 17f8ad430..6115ef924 100644 --- a/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs +++ b/src/persistence/Elsa.Persistence.YesSql/Stores/YesSqlStore.cs @@ -48,7 +48,7 @@ namespace Elsa.Persistence.YesSql.Stores var document = Mapper.Map(entity, existingDocument); session.Save(document, CollectionName); await session.SaveChangesAsync(); - } + } finally { _semaphore.Release(); From 8d0376b420f62269bcca891c60ccb431b036e4ef Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Mon, 5 Jul 2021 11:47:38 +0300 Subject: [PATCH 10/10] Webhooks DefinitionId should be not nullable Webhooks DefinitionId should be not nullable --- .../webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs index b645192ff..c8455ec3f 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Migrations.cs @@ -11,7 +11,7 @@ namespace Elsa.Webhooks.Persistence.YesSql { SchemaBuilder.CreateMapIndexTable( table => table - .Column(nameof(WebhookDefinitionIndex.DefinitionId)) + .Column(nameof(WebhookDefinitionIndex.DefinitionId)) .Column(nameof(WebhookDefinitionIndex.TenantId)) .Column(nameof(WebhookDefinitionIndex.IsEnabled)), CollectionNames.WebhookDefinitions);