Skip to content

Commit 5a7f7bb

Browse files
committed
Add MySQL Persistence Provider
1 parent 8d37bcd commit 5a7f7bb

21 files changed

+476
-1
lines changed

WorkflowCore.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample17", "sr
113113
EndProject
114114
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.QueueProviders.SqlServer", "src\providers\WorkflowCore.QueueProviders.SqlServer\WorkflowCore.QueueProviders.SqlServer.csproj", "{7EDD9353-F5C2-414C-AE51-4B0F1C5E105A}"
115115
EndProject
116-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Providers.AWS", "src\providers\WorkflowCore.Providers.AWS\WorkflowCore.Providers.AWS.csproj", "{5E82A137-0954-46A1-8C46-13C00F0E4842}"
116+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Providers.AWS", "src\providers\WorkflowCore.Providers.AWS\WorkflowCore.Providers.AWS.csproj", "{5E82A137-0954-46A1-8C46-13C00F0E4842}"
117+
EndProject
118+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.MySQL", "src\providers\WorkflowCore.Persistence.MySQL\WorkflowCore.Persistence.MySQL.csproj", "{453E260D-DBDC-4DDC-BC9C-CA500CED7897}"
119+
EndProject
120+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.MySQL", "test\WorkflowCore.Tests.MySQL\WorkflowCore.Tests.MySQL.csproj", "{DF7F7ECA-1771-40C9-9CD0-AFEFC44E60DE}"
117121
EndProject
118122
Global
119123
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -289,6 +293,14 @@ Global
289293
{5E82A137-0954-46A1-8C46-13C00F0E4842}.Debug|Any CPU.Build.0 = Debug|Any CPU
290294
{5E82A137-0954-46A1-8C46-13C00F0E4842}.Release|Any CPU.ActiveCfg = Release|Any CPU
291295
{5E82A137-0954-46A1-8C46-13C00F0E4842}.Release|Any CPU.Build.0 = Release|Any CPU
296+
{453E260D-DBDC-4DDC-BC9C-CA500CED7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
297+
{453E260D-DBDC-4DDC-BC9C-CA500CED7897}.Debug|Any CPU.Build.0 = Debug|Any CPU
298+
{453E260D-DBDC-4DDC-BC9C-CA500CED7897}.Release|Any CPU.ActiveCfg = Release|Any CPU
299+
{453E260D-DBDC-4DDC-BC9C-CA500CED7897}.Release|Any CPU.Build.0 = Release|Any CPU
300+
{DF7F7ECA-1771-40C9-9CD0-AFEFC44E60DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
301+
{DF7F7ECA-1771-40C9-9CD0-AFEFC44E60DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
302+
{DF7F7ECA-1771-40C9-9CD0-AFEFC44E60DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
303+
{DF7F7ECA-1771-40C9-9CD0-AFEFC44E60DE}.Release|Any CPU.Build.0 = Release|Any CPU
292304
EndGlobalSection
293305
GlobalSection(SolutionProperties) = preSolution
294306
HideSolutionNode = FALSE
@@ -339,6 +351,8 @@ Global
339351
{42F475BC-95F4-42E1-8CCD-7B9C27487E33} = {5080DB09-CBE8-4C45-9957-C3BB7651755E}
340352
{7EDD9353-F5C2-414C-AE51-4B0F1C5E105A} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2}
341353
{5E82A137-0954-46A1-8C46-13C00F0E4842} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2}
354+
{453E260D-DBDC-4DDC-BC9C-CA500CED7897} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2}
355+
{DF7F7ECA-1771-40C9-9CD0-AFEFC44E60DE} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB}
342356
EndGlobalSection
343357
GlobalSection(ExtensibilityGlobals) = postSolution
344358
SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.EntityFrameworkCore.Infrastructure;
4+
using Microsoft.EntityFrameworkCore.Metadata.Builders;
5+
using WorkflowCore.Persistence.EntityFramework.Models;
6+
using WorkflowCore.Persistence.EntityFramework.Services;
7+
8+
namespace WorkflowCore.Persistence.MySQL
9+
{
10+
public class MysqlContext : WorkflowDbContext
11+
{
12+
private readonly string _connectionString;
13+
private readonly Action<MySqlDbContextOptionsBuilder> _mysqlOptionsAction;
14+
15+
public MysqlContext(string connectionString, Action<MySqlDbContextOptionsBuilder> mysqlOptionsAction = null)
16+
: base()
17+
{
18+
_connectionString = connectionString;
19+
_mysqlOptionsAction = mysqlOptionsAction;
20+
}
21+
22+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
23+
{
24+
base.OnConfiguring(optionsBuilder);
25+
optionsBuilder.UseMySql(_connectionString, _mysqlOptionsAction);
26+
}
27+
28+
protected override void ConfigureSubscriptionStorage(EntityTypeBuilder<PersistedSubscription> builder)
29+
{
30+
builder.ToTable("Subscription");
31+
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd();
32+
}
33+
34+
protected override void ConfigureWorkflowStorage(EntityTypeBuilder<PersistedWorkflow> builder)
35+
{
36+
builder.ToTable("Workflow");
37+
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd();
38+
}
39+
40+
protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder<PersistedExecutionPointer> builder)
41+
{
42+
builder.ToTable("ExecutionPointer");
43+
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd();
44+
}
45+
46+
protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder<PersistedExecutionError> builder)
47+
{
48+
builder.ToTable("ExecutionError");
49+
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd();
50+
}
51+
52+
protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder<PersistedExtensionAttribute> builder)
53+
{
54+
builder.ToTable("ExtensionAttribute");
55+
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd();
56+
}
57+
58+
protected override void ConfigureEventStorage(EntityTypeBuilder<PersistedEvent> builder)
59+
{
60+
builder.ToTable("Event");
61+
builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd();
62+
}
63+
}
64+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Microsoft.EntityFrameworkCore.Infrastructure;
2+
using System;
3+
using WorkflowCore.Persistence.EntityFramework.Interfaces;
4+
using WorkflowCore.Persistence.EntityFramework.Services;
5+
6+
namespace WorkflowCore.Persistence.MySQL
7+
{
8+
public class MysqlContextFactory : IWorkflowDbContextFactory
9+
{
10+
private readonly string _connectionString;
11+
private readonly Action<MySqlDbContextOptionsBuilder> _mysqlOptionsAction;
12+
13+
public MysqlContextFactory(string connectionString, Action<MySqlDbContextOptionsBuilder> mysqlOptionsAction = null)
14+
{
15+
_connectionString = connectionString;
16+
_mysqlOptionsAction = mysqlOptionsAction;
17+
}
18+
19+
public WorkflowDbContext Build()
20+
{
21+
return new MysqlContext(_connectionString, _mysqlOptionsAction);
22+
}
23+
}
24+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# MySQL Persistence provider for Workflow Core
2+
3+
Provides support to persist workflows running on [Workflow Core](../../README.md) to a MySQL database.
4+
5+
## Installing
6+
7+
Install the NuGet package "WorkflowCore.Persistence.MySQL"
8+
9+
```
10+
PM> Install-Package WorkflowCore.Persistence.MySQL -Pre
11+
```
12+
13+
## Usage
14+
15+
Use the .UseMySQL extension method when building your service provider.
16+
17+
```C#
18+
services.AddWorkflow(x => x.UseMySQL(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true));
19+
```
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using Microsoft.EntityFrameworkCore.Infrastructure;
3+
using WorkflowCore.Models;
4+
using WorkflowCore.Persistence.EntityFramework.Services;
5+
using WorkflowCore.Persistence.MySQL;
6+
7+
namespace Microsoft.Extensions.DependencyInjection
8+
{
9+
public static class ServiceCollectionExtensions
10+
{
11+
public static WorkflowOptions UseMySQL(this WorkflowOptions options, string connectionString, bool canCreateDB, Action<MySqlDbContextOptionsBuilder> mysqlOptionsAction = null)
12+
{
13+
options.UsePersistence(sp => new EntityFrameworkPersistenceProvider(new MysqlContextFactory(connectionString, mysqlOptionsAction), canCreateDB, false));
14+
return options;
15+
}
16+
}
17+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1">
9+
<PrivateAssets>all</PrivateAssets>
10+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
11+
</PackageReference>
12+
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.0.1" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\..\WorkflowCore\WorkflowCore.csproj" />
17+
<ProjectReference Include="..\WorkflowCore.Persistence.EntityFramework\WorkflowCore.Persistence.EntityFramework.csproj" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Collections.Generic;
2+
using Docker.Testify;
3+
using Xunit;
4+
using MySql.Data.MySqlClient;
5+
using System;
6+
7+
namespace WorkflowCore.Tests.MySQL
8+
{
9+
public class MysqlDockerSetup : DockerSetup
10+
{
11+
public static string ConnectionString { get; set; }
12+
public static string ScenarioConnectionString { get; set; }
13+
public static string RootPassword => "rootpwd123";
14+
15+
public override string ImageTag => "5.7.24";
16+
public override string ImageName => "mysql";
17+
public override IList<string> EnvironmentVariables => new List<string> {
18+
$"MYSQL_ROOT_PASSWORD={RootPassword}"
19+
};
20+
21+
public override int InternalPort => 3306;
22+
23+
public override void PublishConnectionInfo()
24+
{
25+
ConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=workflow;User=root;Password={RootPassword};";
26+
ScenarioConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=scenarios;User=root;Password={RootPassword};";
27+
}
28+
29+
public override bool TestReady()
30+
{
31+
try
32+
{
33+
var connection = new MySqlConnection($"host=127.0.0.1;port={ExternalPort};user=root;password={RootPassword};database=mysql;");
34+
connection.Open();
35+
connection.Close();
36+
return true;
37+
}
38+
catch
39+
{
40+
return false;
41+
}
42+
43+
}
44+
}
45+
46+
[CollectionDefinition("Mysql collection")]
47+
public class MysqlCollection : ICollectionFixture<MysqlDockerSetup>
48+
{
49+
}
50+
51+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using WorkflowCore.Interface;
2+
using WorkflowCore.Persistence.EntityFramework.Services;
3+
using WorkflowCore.Persistence.MySQL;
4+
using WorkflowCore.UnitTests;
5+
using Xunit;
6+
using Xunit.Abstractions;
7+
8+
namespace WorkflowCore.Tests.MySQL
9+
{
10+
[Collection("Mysql collection")]
11+
public class MysqlPersistenceProviderFixture : BasePersistenceFixture
12+
{
13+
private readonly IPersistenceProvider _subject;
14+
protected override IPersistenceProvider Subject => _subject;
15+
16+
public MysqlPersistenceProviderFixture(MysqlDockerSetup dockerSetup, ITestOutputHelper output)
17+
{
18+
output.WriteLine($"Connecting on {MysqlDockerSetup.ConnectionString}");
19+
_subject = new EntityFrameworkPersistenceProvider(new MysqlContextFactory(MysqlDockerSetup.ConnectionString), true, false);
20+
_subject.EnsureStoreExists();
21+
}
22+
}
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using WorkflowCore.IntegrationTests.Scenarios;
3+
using Xunit;
4+
5+
namespace WorkflowCore.Tests.MySQL.Scenarios
6+
{
7+
[Collection("Mysql collection")]
8+
public class MysqlBasicScenario : BasicScenario
9+
{
10+
protected override void ConfigureServices(IServiceCollection services)
11+
{
12+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
13+
}
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using WorkflowCore.IntegrationTests.Scenarios;
3+
using Xunit;
4+
5+
namespace WorkflowCore.Tests.MySQL.Scenarios
6+
{
7+
[Collection("Mysql collection")]
8+
public class MysqlDataScenario : DataIOScenario
9+
{
10+
protected override void ConfigureServices(IServiceCollection services)
11+
{
12+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
13+
}
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using WorkflowCore.IntegrationTests.Scenarios;
4+
using WorkflowCore.Tests.MySQL;
5+
using Xunit;
6+
7+
namespace WorkflowCore.Tests.MySQL.Scenarios
8+
{
9+
[Collection("Mysql collection")]
10+
public class MysqlDynamicDataScenario : DynamicDataIOScenario
11+
{
12+
protected override void ConfigureServices(IServiceCollection services)
13+
{
14+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
15+
}
16+
}
17+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using WorkflowCore.IntegrationTests.Scenarios;
6+
using WorkflowCore.Tests.MySQL;
7+
using Xunit;
8+
9+
namespace WorkflowCore.Tests.MySQL.Scenarios
10+
{
11+
[Collection("Mysql collection")]
12+
public class MysqlEventScenario : EventScenario
13+
{
14+
protected override void ConfigureServices(IServiceCollection services)
15+
{
16+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using WorkflowCore.IntegrationTests.Scenarios;
6+
using WorkflowCore.Tests.MySQL;
7+
using Xunit;
8+
9+
namespace WorkflowCore.Tests.MySQL.Scenarios
10+
{
11+
[Collection("Mysql collection")]
12+
public class MysqlForeachScenario : ForeachScenario
13+
{
14+
protected override void ConfigureServices(IServiceCollection services)
15+
{
16+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using WorkflowCore.IntegrationTests.Scenarios;
6+
using WorkflowCore.Tests.MySQL;
7+
using Xunit;
8+
9+
namespace WorkflowCore.Tests.MySQL.Scenarios
10+
{
11+
[Collection("Mysql collection")]
12+
public class MysqlForkScenario : ForkScenario
13+
{
14+
protected override void Configure(IServiceCollection services)
15+
{
16+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
17+
}
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using WorkflowCore.IntegrationTests.Scenarios;
6+
using WorkflowCore.Tests.MySQL;
7+
using Xunit;
8+
9+
namespace WorkflowCore.Tests.MySQL.Scenarios
10+
{
11+
[Collection("Mysql collection")]
12+
public class MysqlIfScenario : IfScenario
13+
{
14+
protected override void ConfigureServices(IServiceCollection services)
15+
{
16+
services.AddWorkflow(x => x.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true));
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)