From 9575cdeecf8800c68c96a3e836aed6bc5e51dc7b Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 20 Mar 2025 12:11:05 +0100 Subject: [PATCH] Update Dapper Migrations (#6520) * Update workflow to check for patch version 3.3.3 Revised the GitHub Actions workflow to detect the correct patch branch, updating from version 3.3.2 to 3.3.3. This ensures compatibility with the latest release process. * Refactor WebhooksFeature to streamline configuration. Simplified the configuration of sinks, sources, and HTTP clients by using direct actions instead of service-level options. Updated Apply method to finalize configurations and added notification handlers for better extensibility. Improved code readability and maintainability by consolidating logic and removing unnecessary dependencies. * Update base_version in GitHub Actions workflow Bump the base_version from 3.3.2 to 3.3.4 in the packages workflow file. This ensures compatibility and uses the latest base version for package management. * Update release branch check to target patch 3.3.4 Modified the GitHub Actions workflow to check for the `patch/3.3.4` branch instead of `patch/3.3.3` during release events. This ensures compatibility with the latest patch branch in the release process. * Handle conversion of enumerables to arrays in ObjectConverter (#6508) * Handle conversion of enumerables to arrays in ObjectConverter Added functionality to convert enumerables to arrays when the target type is an array. The implementation ensures each item is properly cast to the target array's element type and then added to the resulting array. * Add unit test for converting object array to double array This commit introduces a new test ensuring the proper conversion of an object array of doubles to a double array. It verifies both the validity of the conversion and that the result is not null. * Update base version to 3.3.5 in workflow configuration Bump the `base_version` from 3.3.4 to 3.3.5 in the GitHub Actions workflow file. Adjust the matching branch reference to correspond with the updated version. * Add V3.4 migration with schema updates and new column Introduces Migration V3_4 to modify WorkflowInstances by adding the IsExecuting column. Updates Entity Framework migration to dynamically handle schema changes across tables. Ensures improved compatibility and extendability within the database layer. * Refactor Dapper migration execution and update database schema. (#6519) * Refactor migration execution and update database schema. Replaced RunMigrationsHostedService with RunMigrationsStartupTask using IStartupTask for improved lifecycle management. Updated DapperMigrationsFeature to use the new startup task. Added a new "SerializedProperties" column to ActivityExecutionRecords and ensured proper schema adjustments during migrations. * Add TenantId column to BookmarkQueueItems table This commit introduces a nullable TenantId column to the BookmarkQueueItems table. The change ensures better multi-tenancy support by allowing tenant-specific data segregation. --- .../Elsa.Dapper.Migrations/Management/V3_4.cs | 24 ++++++++++++++ .../Elsa.Dapper.Migrations/Runtime/V3_3.cs | 5 ++- .../Features/DapperMigrationsFeature.cs | 15 ++------- .../RunMigrationsHostedService.cs | 33 ------------------- .../RunMigrationsStartupTask.cs | 18 ++++++++++ .../Identity/20250222190924_V3_4.cs | 9 ++--- 6 files changed, 54 insertions(+), 50 deletions(-) create mode 100644 src/modules/Elsa.Dapper.Migrations/Management/V3_4.cs delete mode 100644 src/modules/Elsa.Dapper/HostedServices/RunMigrationsHostedService.cs create mode 100644 src/modules/Elsa.Dapper/HostedServices/RunMigrationsStartupTask.cs diff --git a/src/modules/Elsa.Dapper.Migrations/Management/V3_4.cs b/src/modules/Elsa.Dapper.Migrations/Management/V3_4.cs new file mode 100644 index 000000000..f4d8cff75 --- /dev/null +++ b/src/modules/Elsa.Dapper.Migrations/Management/V3_4.cs @@ -0,0 +1,24 @@ +using System.Diagnostics.CodeAnalysis; +using FluentMigrator; +using JetBrains.Annotations; + +namespace Elsa.Dapper.Migrations.Management; + +/// +[Migration(10005, "Elsa:Management:V3.4")] +[PublicAPI] +[SuppressMessage("ReSharper", "InconsistentNaming")] +public class V3_4: Migration +{ + /// + public override void Up() + { + Alter.Table("WorkflowInstances").AddColumn("IsExecuting").AsBoolean().NotNullable().WithDefaultValue(false); + } + + /// + public override void Down() + { + Delete.Column("IsExecuting").FromTable("WorkflowInstances"); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper.Migrations/Runtime/V3_3.cs b/src/modules/Elsa.Dapper.Migrations/Runtime/V3_3.cs index bbe82ae9f..9e612040b 100644 --- a/src/modules/Elsa.Dapper.Migrations/Runtime/V3_3.cs +++ b/src/modules/Elsa.Dapper.Migrations/Runtime/V3_3.cs @@ -18,13 +18,14 @@ public class V3_3 : Migration Alter.Table("Bookmarks").AddColumn("TenantId").AsString().Nullable(); Alter.Table("WorkflowExecutionLogRecords").AddColumn("TenantId").AsString().Nullable(); Alter.Table("ActivityExecutionRecords").AddColumn("TenantId").AsString().Nullable(); + Alter.Table("ActivityExecutionRecords").AddColumn("SerializedProperties").AsString(MaxValue).Nullable(); Alter.Table("KeyValuePairs").AddColumn("TenantId").AsString().Nullable(); - Rename.Column("Key").OnTable("KeyValuePairs").To("Id"); IfDatabase("SqlServer", "Oracle", "MySql", "Postgres") .Create .Table("BookmarkQueueItems") .WithColumn("Id").AsString().PrimaryKey() + .WithColumn("TenantId").AsString().Nullable() .WithColumn("WorkflowInstanceId").AsString().Nullable() .WithColumn("CorrelationId").AsString().Nullable() .WithColumn("BookmarkId").AsString().Nullable() @@ -38,6 +39,7 @@ public class V3_3 : Migration .Create .Table("BookmarkQueueItems") .WithColumn("Id").AsString().PrimaryKey() + .WithColumn("TenantId").AsString().Nullable() .WithColumn("WorkflowInstanceId").AsString().Nullable() .WithColumn("CorrelationId").AsString().Nullable() .WithColumn("BookmarkId").AsString().Nullable() @@ -55,6 +57,7 @@ public class V3_3 : Migration Delete.Column("TenantId").FromTable("Bookmarks"); Delete.Column("TenantId").FromTable("WorkflowExecutionLogRecords"); Delete.Column("TenantId").FromTable("ActivityExecutionRecords"); + Delete.Column("SerializedProperties").FromTable("ActivityExecutionRecords"); Delete.Column("TenantId").FromTable("KeyValuePairs"); Rename.Column("Id").OnTable("KeyValuePairs").To("Key"); Delete.Table("BookmarkQueueItems"); diff --git a/src/modules/Elsa.Dapper/Features/DapperMigrationsFeature.cs b/src/modules/Elsa.Dapper/Features/DapperMigrationsFeature.cs index 9cee0c44f..b04bd10e2 100644 --- a/src/modules/Elsa.Dapper/Features/DapperMigrationsFeature.cs +++ b/src/modules/Elsa.Dapper/Features/DapperMigrationsFeature.cs @@ -1,6 +1,7 @@ using Elsa.Dapper.Contracts; using Elsa.Dapper.HostedServices; using Elsa.Dapper.Migrations.Management; +using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Services; using FluentMigrator.Runner; @@ -11,13 +12,8 @@ namespace Elsa.Dapper.Features; /// /// Configures migrations. /// -public class DapperMigrationsFeature : FeatureBase +public class DapperMigrationsFeature(IModule module) : FeatureBase(module) { - /// - public DapperMigrationsFeature(IModule module) : base(module) - { - } - /// /// Configures migrations to use SQLite. /// @@ -48,11 +44,6 @@ public class DapperMigrationsFeature : FeatureBase { Services.AddFluentMigratorCore(); Services.ConfigureRunner(ConfigureRunner); - } - - /// - public override void ConfigureHostedServices() - { - ConfigureHostedService(-1); + Services.AddStartupTask(); } } \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/HostedServices/RunMigrationsHostedService.cs b/src/modules/Elsa.Dapper/HostedServices/RunMigrationsHostedService.cs deleted file mode 100644 index a093f095a..000000000 --- a/src/modules/Elsa.Dapper/HostedServices/RunMigrationsHostedService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using FluentMigrator.Runner; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace Elsa.Dapper.HostedServices; - -/// -/// Runs database migrations on startup. -/// -public class RunMigrationsHostedService : IHostedService -{ - private readonly IServiceScopeFactory _scopeFactory; - - /// - /// Initializes a new instance of the class. - /// - public RunMigrationsHostedService(IServiceScopeFactory scopeFactory) - { - _scopeFactory = scopeFactory; - } - - /// - public Task StartAsync(CancellationToken cancellationToken) - { - using var scope = _scopeFactory.CreateScope(); - var runner = scope.ServiceProvider.GetRequiredService(); - runner.MigrateUp(); - return Task.CompletedTask; - } - - /// - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; -} \ No newline at end of file diff --git a/src/modules/Elsa.Dapper/HostedServices/RunMigrationsStartupTask.cs b/src/modules/Elsa.Dapper/HostedServices/RunMigrationsStartupTask.cs new file mode 100644 index 000000000..fa82e4e5e --- /dev/null +++ b/src/modules/Elsa.Dapper/HostedServices/RunMigrationsStartupTask.cs @@ -0,0 +1,18 @@ +using Elsa.Common; +using FluentMigrator.Runner; +using JetBrains.Annotations; + +namespace Elsa.Dapper.HostedServices; + +/// +/// Runs database migrations on startup. +/// +[UsedImplicitly] +public class RunMigrationsStartupTask(IMigrationRunner migrationRunner) : IStartupTask +{ + public Task ExecuteAsync(CancellationToken cancellationToken) + { + migrationRunner.MigrateUp(); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20250222190924_V3_4.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20250222190924_V3_4.cs index 09f2cd14f..22201862b 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20250222190924_V3_4.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Migrations/Identity/20250222190924_V3_4.cs @@ -1,3 +1,4 @@ +using Elsa.Extensions; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable @@ -19,22 +20,22 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Identity protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( - name: "Elsa"); + name: _schema.Schema); migrationBuilder.RenameTable( name: "Users", newName: "Users", - newSchema: "Elsa"); + newSchema: _schema.Schema); migrationBuilder.RenameTable( name: "Roles", newName: "Roles", - newSchema: "Elsa"); + newSchema: _schema.Schema); migrationBuilder.RenameTable( name: "Applications", newName: "Applications", - newSchema: "Elsa"); + newSchema: _schema.Schema); } ///