Incremental work on migrations

This commit is contained in:
Sipke Schoorstra 2020-10-10 22:14:10 +02:00
parent 1a85fc5f26
commit 5b02ca2813
12 changed files with 118 additions and 19 deletions

View file

@ -1,11 +1,14 @@
using System;
using Elsa.Activities.Http;
using Elsa.Activities.Http.Indexes;
using Elsa.Activities.Http.Models;
using Elsa.Activities.Http.Options;
using Elsa.Activities.Http.Parsers;
using Elsa.Activities.Http.RequestHandlers.Handlers;
using Elsa.Activities.Http.Services;
using Elsa.Data;
using Elsa.Extensions;
using Elsa.Indexes;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -37,7 +40,8 @@ namespace Microsoft.Extensions.DependencyInjection
.AddSingleton<IHttpResponseBodyParser, JsonHttpResponseBodyParser>()
.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
.AddSingleton<IAbsoluteUrlProvider, DefaultAbsoluteUrlProvider>()
.AddTypeAlias<HttpResponseHeaders>()
.AddIndexProvider<WorkflowInstanceByReceiveHttpRequestIndexProvider>()
.AddDataMigration<Migrations>()
.AddHttpContextAccessor()
.AddNotificationHandlers(typeof(ServiceCollectionExtensions))
.AddDataProtection();

View file

@ -1,4 +1,7 @@
using YesSql.Indexes;
using System.Linq;
using Elsa.Indexes;
using Elsa.Models;
using YesSql.Indexes;
namespace Elsa.Activities.Http.Indexes
{
@ -8,4 +11,42 @@ namespace Elsa.Activities.Http.Indexes
public string RequestPath { get; set; } = default!;
public string? RequestMethod { get; set; }
}
public class WorkflowInstanceByReceiveHttpRequestIndexProvider : IndexProvider<WorkflowInstance>
{
public override void Describe(DescribeContext<WorkflowInstance> context)
{
context.For<WorkflowInstanceIndex>()
.Map(
workflowInstance => new WorkflowInstanceIndex
{
WorkflowInstanceId = workflowInstance.WorkflowInstanceId,
WorkflowDefinitionId = workflowInstance.WorkflowDefinitionId,
WorkflowStatus = workflowInstance.Status,
CorrelationId = workflowInstance.CorrelationId,
CreatedAt = workflowInstance.CreatedAt
});
context.For<WorkflowInstanceByReceiveHttpRequestIndex>()
.Map(
workflowInstance => workflowInstance.BlockingActivities
.Where(x => x.ActivityType == nameof(ReceiveHttpRequest))
.Select(
blockingActivity =>
{
var activity = workflowInstance.Activities
.First(x => x.Id == blockingActivity.ActivityId);
var path = activity.Data.Value<string>(nameof(ReceiveHttpRequest.Path));
var method = activity.Data.Value<string>(nameof(ReceiveHttpRequest.Method));
return new WorkflowInstanceByReceiveHttpRequestIndex
{
ActivityId = blockingActivity.ActivityId,
RequestPath = path,
RequestMethod = method
};
}));
}
}
}

View file

@ -0,0 +1,19 @@
using Elsa.Activities.Http.Indexes;
using Elsa.Data;
using YesSql.Sql;
namespace Elsa.Activities.Http
{
public class Migrations : DataMigration
{
public int Create()
{
SchemaBuilder.CreateMapIndexTable<WorkflowInstanceByReceiveHttpRequestIndex>(table => table
.Column<string>("ActivityId")
.Column<string>("RequestPath")
.Column<string?>("RequestMethod"));
return 1;
}
}
}

View file

@ -3,6 +3,6 @@
public static class CollectionNames
{
public static string WorkflowDefinitions = "WorkflowDefinitions";
public static string WorkflowInstances = "WorkflowDefinitions";
public static string WorkflowInstances = "WorkflowInstances";
}
}

View file

@ -1,15 +1,10 @@
using Elsa.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using YesSql.Indexes;
namespace Elsa.Data
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddWorkflowProvider<T>(this IServiceCollection services)
where T : class, IWorkflowProvider =>
services.AddTransient<IWorkflowProvider, T>();
public static IServiceCollection AddIndexProvider<T>(this IServiceCollection services)
where T : class, IIndexProvider =>
services.AddSingleton<IIndexProvider, T>();
@ -17,5 +12,9 @@ namespace Elsa.Data
public static IServiceCollection AddScopedIndexProvider<T>(this IServiceCollection services)
where T : class, IIndexProvider =>
services.AddScoped<IScopedIndexProvider>();
public static IServiceCollection AddDataMigration<T>(this IServiceCollection services)
where T : class, IDataMigration =>
services.AddScoped<IDataMigration, T>();
}
}

View file

@ -1,10 +1,14 @@
using System;
using System.Data;
using System.Linq;
using Dapper;
using Elsa.Data.Services;
using Elsa.Runtime;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using YesSql;
using YesSql.Indexes;
using ISession = YesSql.ISession;
namespace Elsa.Data.Extensions
{
@ -20,7 +24,8 @@ namespace Elsa.Data.Extensions
.AddScoped(CreateSession)
.AddSingleton<IDataMigrationManager, DataMigrationManager>()
.AddStartupTask<DatabaseInitializer>()
.AddStartupTask<DataMigrationsRunner>();
.AddStartupTask<DataMigrationsRunner>()
.AddDataMigration<Migrations>();
return services;
}
@ -36,6 +41,8 @@ namespace Elsa.Data.Extensions
var store = StoreFactory.CreateAndInitializeAsync(configuration).GetAwaiter().GetResult();
//var store = StoreFactory.Create(configuration);
SqlMapper.AddTypeMap(typeof(PathString), DbType.String);
var indexes = serviceProvider.GetServices<IIndexProvider>();
store.RegisterIndexes(indexes);

View file

@ -40,7 +40,7 @@ namespace Elsa.Data.Services
public async Task RunAllAsync()
{
var migrationsToUpdate = await GetMigrationsThatNeedUpdateAsync();
foreach (var migration in migrationsToUpdate)
{
try
@ -52,6 +52,8 @@ namespace Elsa.Data.Services
_logger.LogError(ex, "Could not run migrations automatically on '{FeatureName}'", migration);
}
}
await _session.CommitAsync();
}
public async Task<IEnumerable<IDataMigration>> GetMigrationsThatNeedUpdateAsync()
@ -241,7 +243,8 @@ namespace Elsa.Data.Services
{
var flags = BindingFlags.Public | BindingFlags.Instance;
var methodInfo = dataMigration.GetType().GetMethod(name, flags);
return methodInfo != null && methodInfo.ReturnType == typeof(Task<int>) ? methodInfo : null;
var returnType = methodInfo?.ReturnType;
return returnType != null && (returnType == typeof(Task<int>) || returnType == typeof(int)) ? methodInfo : null;
}
}
}

View file

@ -32,6 +32,7 @@
<PackageReference Include="Humanizer.Core" Version="2.8.26" />
<PackageReference Include="MediatR" Version="8.1.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.7" />

View file

@ -6,6 +6,7 @@ using Elsa.Activities.Primitives;
using Elsa.Activities.Signaling;
using Elsa.Builders;
using Elsa.Converters;
using Elsa.Data;
using Elsa.Data.Extensions;
using Elsa.Expressions;
using Elsa.Extensions;
@ -107,7 +108,8 @@ namespace Microsoft.Extensions.DependencyInjection
.AddSingleton<IWorkflowSchedulerQueue, WorkflowSchedulerQueue>()
.AddScoped<IWorkflowHost, WorkflowHost>()
.AddSingleton<IWorkflowActivator, WorkflowActivator>()
.AddSingleton<IIndexProvider, WorkflowDefinitionIndexProvider>()
.AddIndexProvider<WorkflowDefinitionIndexProvider>()
.AddIndexProvider<WorkflowInstanceIndexProvider>()
.AddStartupRunner()
.AddTransient<IActivityResolver, ActivityResolver>()
.AddWorkflowProvider<CodeWorkflowProvider>()

View file

@ -1,4 +1,7 @@
using Elsa.Data;
using System.Data;
using Elsa.Data;
using Elsa.Indexes;
using YesSql.Sql;
namespace Elsa
{
@ -6,7 +9,28 @@ namespace Elsa
{
public int Create()
{
//SchemaBuilder.CreateMapIndexTable<>()
SchemaBuilder.CreateMapIndexTable<WorkflowDefinitionIndex>(table => table
.Column<string>("WorkflowDefinitionId")
.Column<string>("WorkflowDefinitionVersionId")
.Column<int>("Version")
.Column<bool>("IsLatest")
.Column<bool>("IsPublished")
.Column<bool>("IsEnabled"));
SchemaBuilder.CreateMapIndexTable<WorkflowInstanceIndex>(table => table
.Column<string>("WorkflowInstanceId")
.Column<string>("WorkflowDefinitionId")
.Column<string?>("CorrelationId")
.Column("WorkflowStatus", DbType.String)
.Column("CreatedAt", DbType.DateTimeOffset));
SchemaBuilder.CreateMapIndexTable<WorkflowInstanceBlockingActivitiesIndex>(table => table
.Column<string>("ActivityId")
.Column<string>("ActivityType")
.Column<string?>("CorrelationId")
.Column("WorkflowStatus", DbType.String)
.Column("CreatedAt", DbType.DateTimeOffset));
return 1;
}
}

View file

@ -5,7 +5,6 @@ using Elsa.Builders;
using Elsa.Runtime;
using Elsa.Services;
using Microsoft.Extensions.DependencyInjection;
using YesSql.Provider.Sqlite;
namespace Elsa.Samples.HelloWorldConsole
{
@ -14,8 +13,7 @@ namespace Elsa.Samples.HelloWorldConsole
static async Task Main(string[] args)
{
// Create a service container with Elsa services.
var services = new ServiceCollection()
//.AddElsa(options => options.UsePersistence(config => config.UseSqLite("Data Source=elsa.db;Cache=Shared")))
var services = new ServiceCollection()
.AddElsa()
.AddConsoleActivities()
.AddSingleton(Console.In)

View file

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using YesSql.Provider.Sqlite;
namespace Elsa.Samples.HelloWorldHttp
{
@ -8,7 +9,7 @@ namespace Elsa.Samples.HelloWorldHttp
public void ConfigureServices(IServiceCollection services)
{
services
.AddElsa()
.AddElsa(option => option.UsePersistence(db => db.UseSqLite("Data Source=elsa.db;Cache=Shared")))
.AddHttpActivities()
.AddWorkflow<HelloHttpWorkflow>();
}