diff --git a/README.md b/README.md index 07c05789b..c295eeee6 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ public class MyWorkflow : IWorkflow } ``` -## JSON Workflow Definitions +## JSON / YAML Workflow Definitions -Define your workflows in JSON +Define your workflows in JSON or YAML ```json { @@ -47,6 +47,17 @@ Define your workflows in JSON } ``` +```yaml +Id: HelloWorld +Version: 1 +Steps: +- Id: Hello + StepType: MyApp.HelloWorld, MyApp + NextStepId: Bye +- Id: Bye + StepType: MyApp.GoodbyeWorld, MyApp +``` + ### Sample use cases * New user workflow diff --git a/ReleaseNotes/2.0.0.md b/ReleaseNotes/2.0.0.md new file mode 100644 index 000000000..c4021f4e8 --- /dev/null +++ b/ReleaseNotes/2.0.0.md @@ -0,0 +1,72 @@ +# Workflow Core 2.0.0 + +### Upgrade notes +Existing JSON definitions will be loaded as follows + ```c# + using WorkflowCore.Services.DefinitionStorage; + ... + DefinitionLoader.LoadDefinition(json, Deserializers.Json); + ``` + + +* Targets .NET Standard 2.0 + + The core library now targets .NET Standard 2.0, in order to leverage newer features. + +* Support for YAML definitions + + Added support for YAML workflow definitions, which can be loaded as follows + ```c# + using WorkflowCore.Services.DefinitionStorage; + ... + DefinitionLoader.LoadDefinition(json, Deserializers.Yaml); + ``` + + Existing JSON definitions will be loaded as follows + ```c# + using WorkflowCore.Services.DefinitionStorage; + ... + DefinitionLoader.LoadDefinition(json, Deserializers.Json); + ``` + +* Object graphs and inline expressions on input properties + + You can now pass object graphs to step inputs as opposed to just scalar values + ``` + "inputs": + { + "Body": { + "Value1": 1, + "Value2": 2 + }, + "Headers": { + "Content-Type": "application/json" + } + }, + ``` + If you want to evaluate an expression for a given property of your object, simply prepend and `@` and pass an expression string + ``` + "inputs": + { + "Body": { + "@Value1": "data.MyValue * 2", + "Value2": 5 + }, + "Headers": { + "Content-Type": "application/json" + } + }, + ``` + +* Support for enum values on input properties + + If your step has an enum property, you can now just pass the string representation of the enum value and it will be automatically converted. + +* Environment variables available in input expressions + + You can now access environment variables from within input expressions. + usage: + ``` + environment["VARIABLE_NAME"] + ``` + diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 261e79bde..2caad68c2 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -40,8 +40,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.Po EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.Sqlite", "src\providers\WorkflowCore.Persistence.Sqlite\WorkflowCore.Persistence.Sqlite.csproj", "{86BC1E05-E9CE-4E53-B324-885A2FDBCE74}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.LockProviders.Redlock", "src\providers\WorkflowCore.LockProviders.Redlock\WorkflowCore.LockProviders.Redlock.csproj", "{05250D58-A59E-4212-8D55-E7BC0396E9F5}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.QueueProviders.RabbitMQ", "src\providers\WorkflowCore.QueueProviders.RabbitMQ\WorkflowCore.QueueProviders.RabbitMQ.csproj", "{AFAD87C7-B2EE-451E-BA7E-3F5A91358C48}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample06", "src\samples\WorkflowCore.Sample06\WorkflowCore.Sample06.csproj", "{8FEAFD74-C304-4F75-BA38-4686BE55C891}" @@ -100,6 +98,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNote ReleaseNotes\1.9.0.md = ReleaseNotes\1.9.0.md ReleaseNotes\1.9.2.md = ReleaseNotes\1.9.2.md ReleaseNotes\1.9.3.md = ReleaseNotes\1.9.3.md + ReleaseNotes\2.0.0.md = ReleaseNotes\2.0.0.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample14", "src\samples\WorkflowCore.Sample14\WorkflowCore.Sample14.csproj", "{6BC66637-B42A-4334-ADFB-DBEC9F29D293}" @@ -114,8 +113,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample15", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample16", "src\samples\WorkflowCore.Sample16\WorkflowCore.Sample16.csproj", "{0C9617A9-C8B7-45F6-A54A-261A23AC881B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScratchPad", "test\ScratchPad\ScratchPad.csproj", "{6396453F-4D0E-4CD4-BC89-87E8970F2A80}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample17", "src\samples\WorkflowCore.Sample17\WorkflowCore.Sample17.csproj", "{42F475BC-95F4-42E1-8CCD-7B9C27487E33}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.QueueProviders.SqlServer", "src\providers\WorkflowCore.QueueProviders.SqlServer\WorkflowCore.QueueProviders.SqlServer.csproj", "{7EDD9353-F5C2-414C-AE51-4B0F1C5E105A}" @@ -186,10 +183,6 @@ Global {86BC1E05-E9CE-4E53-B324-885A2FDBCE74}.Debug|Any CPU.Build.0 = Debug|Any CPU {86BC1E05-E9CE-4E53-B324-885A2FDBCE74}.Release|Any CPU.ActiveCfg = Release|Any CPU {86BC1E05-E9CE-4E53-B324-885A2FDBCE74}.Release|Any CPU.Build.0 = Release|Any CPU - {05250D58-A59E-4212-8D55-E7BC0396E9F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {05250D58-A59E-4212-8D55-E7BC0396E9F5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {05250D58-A59E-4212-8D55-E7BC0396E9F5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {05250D58-A59E-4212-8D55-E7BC0396E9F5}.Release|Any CPU.Build.0 = Release|Any CPU {AFAD87C7-B2EE-451E-BA7E-3F5A91358C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFAD87C7-B2EE-451E-BA7E-3F5A91358C48}.Debug|Any CPU.Build.0 = Debug|Any CPU {AFAD87C7-B2EE-451E-BA7E-3F5A91358C48}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -294,10 +287,6 @@ Global {0C9617A9-C8B7-45F6-A54A-261A23AC881B}.Debug|Any CPU.Build.0 = Debug|Any CPU {0C9617A9-C8B7-45F6-A54A-261A23AC881B}.Release|Any CPU.ActiveCfg = Release|Any CPU {0C9617A9-C8B7-45F6-A54A-261A23AC881B}.Release|Any CPU.Build.0 = Release|Any CPU - {6396453F-4D0E-4CD4-BC89-87E8970F2A80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6396453F-4D0E-4CD4-BC89-87E8970F2A80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6396453F-4D0E-4CD4-BC89-87E8970F2A80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6396453F-4D0E-4CD4-BC89-87E8970F2A80}.Release|Any CPU.Build.0 = Release|Any CPU {42F475BC-95F4-42E1-8CCD-7B9C27487E33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42F475BC-95F4-42E1-8CCD-7B9C27487E33}.Debug|Any CPU.Build.0 = Debug|Any CPU {42F475BC-95F4-42E1-8CCD-7B9C27487E33}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -357,7 +346,6 @@ Global {1DE96D4F-F2CA-4740-8764-BADD1000040A} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} {9274B938-3996-4FBA-AE2F-0C82009B1116} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} {86BC1E05-E9CE-4E53-B324-885A2FDBCE74} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} - {05250D58-A59E-4212-8D55-E7BC0396E9F5} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} {AFAD87C7-B2EE-451E-BA7E-3F5A91358C48} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} {8FEAFD74-C304-4F75-BA38-4686BE55C891} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {37B598A8-B054-4ABA-884D-96AEF2511600} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} @@ -384,7 +372,6 @@ Global {EC497168-5347-4E70-9D9E-9C2F826C1CDF} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {9B7811AC-68D6-4D19-B1E9-65423393ED83} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {0C9617A9-C8B7-45F6-A54A-261A23AC881B} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} - {6396453F-4D0E-4CD4-BC89-87E8970F2A80} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {42F475BC-95F4-42E1-8CCD-7B9C27487E33} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {7EDD9353-F5C2-414C-AE51-4B0F1C5E105A} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} {5E82A137-0954-46A1-8C46-13C00F0E4842} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} diff --git a/src/WorkflowCore/Interface/IDefinitionLoader.cs b/src/WorkflowCore/Interface/IDefinitionLoader.cs index cd1cf5fbb..c8870e679 100644 --- a/src/WorkflowCore/Interface/IDefinitionLoader.cs +++ b/src/WorkflowCore/Interface/IDefinitionLoader.cs @@ -1,9 +1,11 @@ -using WorkflowCore.Models; +using System; +using WorkflowCore.Models; +using WorkflowCore.Models.DefinitionStorage.v1; namespace WorkflowCore.Interface { public interface IDefinitionLoader { - WorkflowDefinition LoadDefinition(string json); + WorkflowDefinition LoadDefinition(string source, Func deserializer); } } \ No newline at end of file diff --git a/src/WorkflowCore/Models/DefinitionStorage/v1/StepSourceV1.cs b/src/WorkflowCore/Models/DefinitionStorage/v1/StepSourceV1.cs index fe351fa0f..350da2407 100644 --- a/src/WorkflowCore/Models/DefinitionStorage/v1/StepSourceV1.cs +++ b/src/WorkflowCore/Models/DefinitionStorage/v1/StepSourceV1.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Dynamic; using System.Text; namespace WorkflowCore.Models.DefinitionStorage.v1 @@ -26,7 +27,7 @@ public class StepSourceV1 public string NextStepId { get; set; } - public Dictionary Inputs { get; set; } = new Dictionary(); + public ExpandoObject Inputs { get; set; } = new ExpandoObject(); public Dictionary Outputs { get; set; } = new Dictionary(); diff --git a/src/WorkflowCore/Services/DefinitionStorage/DefinitionLoader.cs b/src/WorkflowCore/Services/DefinitionStorage/DefinitionLoader.cs index fd44f7873..9d37dd9da 100644 --- a/src/WorkflowCore/Services/DefinitionStorage/DefinitionLoader.cs +++ b/src/WorkflowCore/Services/DefinitionStorage/DefinitionLoader.cs @@ -1,11 +1,13 @@ using Newtonsoft.Json; using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Reflection; using System.Text; +using Newtonsoft.Json.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Primitives; @@ -24,10 +26,10 @@ public DefinitionLoader(IWorkflowRegistry registry) _registry = registry; } - public WorkflowDefinition LoadDefinition(string json) + public WorkflowDefinition LoadDefinition(string source, Func deserializer) { - var source = JsonConvert.DeserializeObject(json); - var def = Convert(source); + var sourceObj = deserializer(source); + var def = Convert(sourceObj); _registry.RegisterWorkflow(def); return def; } @@ -171,13 +173,24 @@ private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, Wor { var dataParameter = Expression.Parameter(dataType, "data"); var contextParameter = Expression.Parameter(typeof(IStepExecutionContext), "context"); - var sourceExpr = DynamicExpressionParser.ParseLambda(new [] { dataParameter, contextParameter }, typeof(object), input.Value); + var environmentVarsParameter = Expression.Parameter(typeof(IDictionary), "environment"); + var stepProperty = stepType.GetProperty(input.Key); - var stepParameter = Expression.Parameter(stepType, "step"); - var targetProperty = Expression.Property(stepParameter, input.Key); - var targetExpr = Expression.Lambda(targetProperty, stepParameter); + if (input.Value is string) + { + var acn = BuildScalarInputAction(input, dataParameter, contextParameter, environmentVarsParameter, stepProperty); + step.Inputs.Add(new ActionParameter(acn)); + continue; + } - step.Inputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); + if ((input.Value is IDictionary) || (input.Value is IDictionary)) + { + var acn = BuildObjectInputAction(input, dataParameter, contextParameter, environmentVarsParameter, stepProperty); + step.Inputs.Add(new ActionParameter(acn)); + continue; + } + + throw new ArgumentException($"Unknown type for input {input.Key} on {source.Id}"); } } @@ -221,5 +234,52 @@ private Type FindType(string name) return Type.GetType(name, true, true); } + private static Action BuildScalarInputAction(KeyValuePair input, ParameterExpression dataParameter, ParameterExpression contextParameter, ParameterExpression environmentVarsParameter, PropertyInfo stepProperty) + { + var expr = System.Convert.ToString(input.Value); + var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), expr); + + void acn(IStepBody pStep, object pData, IStepExecutionContext pContext) + { + object resolvedValue = sourceExpr.Compile().DynamicInvoke(pData, pContext, Environment.GetEnvironmentVariables()); + if (stepProperty.PropertyType.IsEnum) + stepProperty.SetValue(pStep, Enum.Parse(stepProperty.PropertyType, (string)resolvedValue, true)); + else + stepProperty.SetValue(pStep, System.Convert.ChangeType(resolvedValue, stepProperty.PropertyType)); + } + return acn; + } + + private static Action BuildObjectInputAction(KeyValuePair input, ParameterExpression dataParameter, ParameterExpression contextParameter, ParameterExpression environmentVarsParameter, PropertyInfo stepProperty) + { + void acn(IStepBody pStep, object pData, IStepExecutionContext pContext) + { + var stack = new Stack(); + var destObj = JObject.FromObject(input.Value); + stack.Push(destObj); + + while (stack.Count > 0) + { + var subobj = stack.Pop(); + foreach (var prop in subobj.Properties().ToList()) + { + if (prop.Name.StartsWith("@")) + { + var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), prop.Value.ToString()); + object resolvedValue = sourceExpr.Compile().DynamicInvoke(pData, pContext, Environment.GetEnvironmentVariables()); + subobj.Remove(prop.Name); + subobj.Add(prop.Name.TrimStart('@'), JToken.FromObject(resolvedValue)); + } + } + + foreach (var child in subobj.Children()) + stack.Push(child); + } + + stepProperty.SetValue(pStep, destObj); + } + return acn; + } + } } diff --git a/src/WorkflowCore/Services/DefinitionStorage/Deserializers.cs b/src/WorkflowCore/Services/DefinitionStorage/Deserializers.cs new file mode 100644 index 000000000..4958f6f09 --- /dev/null +++ b/src/WorkflowCore/Services/DefinitionStorage/Deserializers.cs @@ -0,0 +1,16 @@ +using System; +using Newtonsoft.Json; +using SharpYaml.Serialization; +using WorkflowCore.Models.DefinitionStorage.v1; + +namespace WorkflowCore.Services.DefinitionStorage +{ + public static class Deserializers + { + private static Serializer yamlSerializer = new Serializer(); + + public static Func Json = (source) => JsonConvert.DeserializeObject(source); + + public static Func Yaml = (source) => yamlSerializer.DeserializeInto(source, new DefinitionSourceV1()); + } +} diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 842d03ea2..c9f2258b4 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -3,7 +3,7 @@ Workflow Core Daniel Gerlag - netstandard1.3 + netstandard2.0 WorkflowCore WorkflowCore workflow;.NET;Core;state machine @@ -15,33 +15,26 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 1.9.4 - 1.9.4.0 - 1.9.4.0 + 2.0.0 + 2.0.0.0 + 2.0.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - - - + + + + - - - - - - - - diff --git a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj index 9bb4c502f..2725b4c61 100644 --- a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj +++ b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj @@ -2,9 +2,8 @@ Workflow Core extensions for human workflow - 1.6.2 Daniel Gerlag - netstandard1.3 + netstandard2.0 WorkflowCore.Users WorkflowCore.Users workflow;.NET;Core;state machine;WorkflowCore;human;user @@ -12,15 +11,13 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 1.6.1 - $(PackageTargetFallback);dnxcore50 false false false Provides extensions for Workflow Core to enable human workflows. - 1.8.2 - 1.8.2.0 - 1.8.2.0 + 2.0.0 + 2.0.0.0 + 2.0.0.0 @@ -28,7 +25,7 @@ - + diff --git a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj index 74b5f8181..f12a9630f 100644 --- a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj +++ b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj @@ -2,9 +2,8 @@ Workflow Core REST API - 1.6.0 Daniel Gerlag - netstandard1.6 + netstandard2.0 WorkflowCore.WebAPI WorkflowCore.WebAPI workflow;.NET;Core;state machine;WorkflowCore;REST;API @@ -12,12 +11,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 1.6.1 - $(PackageTargetFallback);dnxcore50 false false false - 1.7.0 + 2.0.0 WebAPI wrapper for Workflow host @@ -28,7 +25,7 @@ - + diff --git a/src/providers/WorkflowCore.LockProviders.Redlock/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.LockProviders.Redlock/Properties/AssemblyInfo.cs deleted file mode 100644 index 4c574c709..000000000 --- a/src/providers/WorkflowCore.LockProviders.Redlock/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WorkflowCore.LockProviders.Redlock")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("05250d58-a59e-4212-8d55-e7bc0396e9f5")] diff --git a/src/providers/WorkflowCore.LockProviders.Redlock/README.md b/src/providers/WorkflowCore.LockProviders.Redlock/README.md deleted file mode 100644 index 866fa762b..000000000 --- a/src/providers/WorkflowCore.LockProviders.Redlock/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Redis Relock DLM provider for Workflow Core - -Provides [DLM](https://en.wikipedia.org/wiki/Distributed_lock_manager) support on [Workflow Core](../../README.md) using [Redis Redlock](http://redis.io/topics/distlock). - -This makes it possible to have a cluster of nodes processing your workflows, along with a queue provider. - -## Installing - -Install the NuGet package "WorkflowCore.LockProviders.Redlock" - -``` -PM> Install-Package WorkflowCore.LockProviders.Redlock -``` - -## Usage - -Use the .UseRedlock extension method when building your service provider. - -```C# -services.AddWorkflow(x => x.UseRedlock(new DnsEndPoint("host1", 6379), new DnsEndPoint("host2", 6379))); -``` \ No newline at end of file diff --git a/src/providers/WorkflowCore.LockProviders.Redlock/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.LockProviders.Redlock/ServiceCollectionExtensions.cs deleted file mode 100644 index 2af4f0597..000000000 --- a/src/providers/WorkflowCore.LockProviders.Redlock/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using WorkflowCore.Models; -using WorkflowCore.LockProviders.Redlock.Services; -using StackExchange.Redis; -using System.Net; - -namespace Microsoft.Extensions.DependencyInjection -{ - public static class ServiceCollectionExtensions - { - public static WorkflowOptions UseRedlock(this WorkflowOptions options, params DnsEndPoint[] endpoints) - { - options.UseDistributedLockManager(sp => new RedlockProvider(endpoints)); - return options; - } - } -} diff --git a/src/providers/WorkflowCore.LockProviders.Redlock/Services/RedlockProvider.cs b/src/providers/WorkflowCore.LockProviders.Redlock/Services/RedlockProvider.cs deleted file mode 100644 index 51273ac3b..000000000 --- a/src/providers/WorkflowCore.LockProviders.Redlock/Services/RedlockProvider.cs +++ /dev/null @@ -1,84 +0,0 @@ -using RedLockNet.SERedis; -using RedLockNet.SERedis.Configuration; -using RedLockNet; -using System; -using System.Collections.Generic; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using WorkflowCore.Interface; - -namespace WorkflowCore.LockProviders.Redlock.Services -{ - public class RedlockProvider : IDistributedLockProvider, IDisposable - { - private readonly RedLockFactory _redlockFactory; - private readonly TimeSpan _lockTimeout = TimeSpan.FromMinutes(10); - private readonly List ManagedLocks = new List(); - - public RedlockProvider(params DnsEndPoint[] endpoints) - { - var redlockEndpoints = new List(); - - foreach (var ep in endpoints) - redlockEndpoints.Add(ep); - - - _redlockFactory = RedLockFactory.Create(redlockEndpoints); - - } - - public async Task AcquireLock(string Id, CancellationToken cancellationToken) - { - - var redLock = await _redlockFactory.CreateLockAsync(Id, _lockTimeout); - - if (redLock.IsAcquired) - { - lock (ManagedLocks) - { - ManagedLocks.Add(redLock); - } - return true; - } - - return false; - } - - - - public Task ReleaseLock(string Id) - { - lock (ManagedLocks) - { - foreach (var redLock in ManagedLocks) - { - if (redLock.Resource == Id) - { - redLock.Dispose(); - ManagedLocks.Remove(redLock); - break; - } - } - } - - return Task.CompletedTask; - } - - public Task Start() - { - return Task.CompletedTask; - } - - public Task Stop() - { - return Task.CompletedTask; - } - - public void Dispose() - { - _redlockFactory?.Dispose(); - } - - } -} \ No newline at end of file diff --git a/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj b/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj deleted file mode 100644 index dc7c6c292..000000000 --- a/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - Workflow Core Redlock distributed lock manager - 1.6.0 - Daniel Gerlag - netstandard1.3 - WorkflowCore.LockProviders.Redlock - WorkflowCore.LockProviders.Redlock - workflow;.NET;Core;state machine;WorkflowCore;Redlock - https://github.com/danielgerlag/workflow-core - https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md - git - https://github.com/danielgerlag/workflow-core.git - 1.6.1 - $(PackageTargetFallback);dnxcore50 - false - false - false - 1.7.0 - - Distributed lock provider for Workflow-core using Redis - 1.7.0.0 - 1.7.0.0 - - - - - - - - - - - - - - - - - diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj index 13a9d87ab..ceb51046d 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj @@ -1,15 +1,15 @@  - netstandard1.3 + netstandard2.0 Distributed lock provider for Workflow-core using SQL Server https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md - 1.7.0 + 2.0.0 - + diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index b8ecefc08..bd48d1a2d 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -2,7 +2,6 @@ Workflow Core EntityFramework Core Persistence Provider - 1.8.0 Daniel Gerlag netstandard2.0 WorkflowCore.Persistence.EntityFramework @@ -15,10 +14,10 @@ false false false - 1.9.1 + 2.0.0 Base package for Workflow-core peristence providers using entity framework - 1.9.1.0 - 1.9.1.0 + 2.0.0.0 + 2.0.0.0 diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 32ce70155..f4a94d337 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -2,9 +2,8 @@ Workflow Core MongoDB Persistence Provider - 1.1.0 Daniel Gerlag - netstandard1.5 + netstandard2.0 WorkflowCore.Persistence.MongoDB WorkflowCore.Persistence.MongoDB workflow;.NET;Core;state machine;WorkflowCore;MongoDB;Mongo @@ -12,15 +11,13 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 1.6.1 - $(PackageTargetFallback);dnxcore50 false false false - 1.9.0 + 2.0.0 Provides support to persist workflows running on Workflow Core to a MongoDB database. - 1.9.0.0 - 1.9.0.0 + 2.0.0.0 + 2.0.0.0 @@ -28,7 +25,7 @@ - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 4524afe6f..e210a8b55 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -2,7 +2,6 @@ Workflow Core PostgreSQL Persistence Provider - 1.8.0 Daniel Gerlag netstandard2.0 WorkflowCore.Persistence.PostgreSQL @@ -16,9 +15,9 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 1.9.1 - 1.9.1.0 - 1.9.1.0 + 2.0.0 + 2.0.0.0 + 2.0.0.0 diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 432d8f1d4..00dc7ae06 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -15,10 +15,10 @@ false false false - 1.9.1 + 2.0.0 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 1.9.1.0 - 1.9.1.0 + 2.0.0.0 + 2.0.0.0 diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index 3d44d7cd0..ad4e4b15b 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -11,15 +11,15 @@ https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git git - 1.9.1 - 1.9.1.0 + 2.0.0 + 2.0.0.0 - + diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index c8dfff7f9..8b67cbfc9 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -1,21 +1,21 @@  - netstandard1.3 + netstandard2.0 Azure providers for Workflow Core - Provides distributed lock management on Workflow Core - Provides Queueing support on Workflow Core workflow workflowcore dlm - 1.9.0 + 2.0.0 $(PackageTargetFallback);dnxcore50 https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git Daniel Gerlag - 1.9.0.0 - 1.9.0.0 + 2.0.0.0 + 2.0.0.0 diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj index a38d3dda5..2f66017f3 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 1.9.0 + 2.0.0 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git @@ -13,7 +13,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index 994f2aebd..e4489cb54 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 1.9.1 + 2.0.0 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core.git git @@ -12,7 +12,7 @@ - + diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index 8cb58ca42..6735f21eb 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj @@ -4,7 +4,7 @@ Workflow Core RabbitMQ queue provider 1.1.0 Daniel Gerlag - netstandard1.3 + netstandard2.0 WorkflowCore.QueueProviders.RabbitMQ WorkflowCore.QueueProviders.RabbitMQ workflow;.NET;Core;state machine;WorkflowCore;RabbitMQ @@ -12,15 +12,13 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 1.6.1 - $(PackageTargetFallback);dnxcore50 false false false - 1.9.0 + 2.0.0 Queue provider for Workflow-core using RabbitMQ - 1.9.0.0 - 1.9.0.0 + 2.0.0.0 + 2.0.0.0 diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 131a20359..205907c87 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -20,9 +20,9 @@ - + - + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index bcbe56b99..1b994fbd8 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 989389d1e..fef512688 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 true WorkflowCore.Sample07 Exe diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 2d05c5ed1..2f99c96b2 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 ScratchPad Exe ScratchPad diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs similarity index 96% rename from test/WorkflowCore.IntegrationTests/Scenarios/StoredScenario.cs rename to test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs index e854c45cb..fcc50b555 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs @@ -10,9 +10,9 @@ namespace WorkflowCore.IntegrationTests.Scenarios { - public class StoredScenario : JsonWorkflowTest + public class StoredJsonScenario : JsonWorkflowTest { - public StoredScenario() + public StoredJsonScenario() { Setup(); } diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs new file mode 100644 index 000000000..820f86bd8 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using WorkflowCore.Testing; +using WorkflowCore.TestAssets.DataTypes; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class StoredYamlScenario : YamlWorkflowTest + { + public StoredYamlScenario() + { + Setup(); + } + + [Fact(DisplayName = "Execute workflow from stored YAML definition")] + public void should_execute_yaml_workflow() + { + var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionYaml(), new CounterBoard() { Flag1 = true, Flag2 = true }); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + var data = GetData(workflowId); + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + data.Counter1.Should().Be(1); + data.Counter2.Should().Be(1); + data.Counter3.Should().Be(1); + data.Counter4.Should().Be(1); + data.Counter5.Should().Be(0); + data.Counter6.Should().Be(1); + } + } +} diff --git a/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs b/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs index 83ec55dd1..286c37d49 100644 --- a/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs +++ b/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs @@ -10,7 +10,6 @@ namespace WorkflowCore.TestAssets.Properties { using System; - using System.Reflection; /// @@ -40,7 +39,7 @@ internal Resources() { public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WorkflowCore.TestAssets.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WorkflowCore.TestAssets.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -71,21 +70,28 @@ internal Resources() { /// { /// "Id": "Step1", /// "StepType": "WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets", - /// - /// "NextStepId": "Generate" + /// "ErrorBehavior": "Retry", + /// "Inputs": { "Value": "data.Counter1" }, + /// "Outputs": { "Counter1": "step.Value" }, + /// "NextStepId": "Step2" /// }, /// { - /// "Id": "Generate", - /// "StepType": "ScratchPad.GenerateMessage, ScratchPad", - /// "NextStepId": "Print", - /// "Outputs": { "Value3": "step.Message" } - /// }, - /// { - /// "I [rest of string was truncated]";. + /// "Id": "Step2", + /// "StepType": "WorkflowCore.TestAsset [rest of string was truncated]";. + /// + public static string stored_definition_json { + get { + return ResourceManager.GetString("stored_definition_json", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. /// - public static string stored_definition { + public static byte[] stored_definition_yaml { get { - return ResourceManager.GetString("stored_definition", resourceCulture); + object obj = ResourceManager.GetObject("stored_definition_yaml", resourceCulture); + return ((byte[])(obj)); } } } diff --git a/test/WorkflowCore.TestAssets/Properties/Resources.resx b/test/WorkflowCore.TestAssets/Properties/Resources.resx index 78ec93e80..5ed7638ee 100644 --- a/test/WorkflowCore.TestAssets/Properties/Resources.resx +++ b/test/WorkflowCore.TestAssets/Properties/Resources.resx @@ -118,7 +118,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + ..\stored-definition.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + ..\stored-definition.yaml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/test/WorkflowCore.TestAssets/Utils.cs b/test/WorkflowCore.TestAssets/Utils.cs index c4f5cae5a..62875e7c1 100644 --- a/test/WorkflowCore.TestAssets/Utils.cs +++ b/test/WorkflowCore.TestAssets/Utils.cs @@ -20,10 +20,14 @@ public static T DeepCopy(T obj) public static string GetTestDefinitionJson() { - //return Properties.Resources.ResourceManager.GetString("stored_definition"); return File.ReadAllText("stored-definition.json"); } + public static string GetTestDefinitionYaml() + { + return File.ReadAllText("stored-definition.yaml"); + } + public static string GetTestDefinitionDynamicJson() { return File.ReadAllText("stored-dynamic-definition.json"); diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index eb4ea7f20..541f2afa9 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -1,11 +1,9 @@  - netstandard1.6 + netstandard2.0 WorkflowCore.TestAssets WorkflowCore.TestAssets - 1.6.1 - $(PackageTargetFallback);dnxcore50 false false false @@ -13,10 +11,14 @@ + + + Always + Always @@ -30,7 +32,7 @@ - + diff --git a/test/WorkflowCore.TestAssets/stored-definition.yaml b/test/WorkflowCore.TestAssets/stored-definition.yaml new file mode 100644 index 000000000..f01efb07b --- /dev/null +++ b/test/WorkflowCore.TestAssets/stored-definition.yaml @@ -0,0 +1,58 @@ +Id: Test +Version: 1 +DataType: WorkflowCore.TestAssets.DataTypes.CounterBoard, WorkflowCore.TestAssets +Steps: +- Id: Step1 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + ErrorBehavior: Retry + Inputs: + Value: data.Counter1 + Outputs: + Counter1: step.Value + NextStepId: Step2 +- Id: Step2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter2 + Outputs: + Counter2: step.Value + NextStepId: Step3 +- Id: Step3 + StepType: WorkflowCore.Primitives.If, WorkflowCore + NextStepId: Step4 + Inputs: + Condition: data.Flag1 + Do: + - - Id: Step3.1.1 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter3 + Outputs: + Counter3: step.Value + NextStepId: Step3.1.2 + - Id: Step3.1.2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter4 + Outputs: + Counter4: step.Value + - - Id: Step3.2.1 + StepType: WorkflowCore.Primitives.WaitFor, WorkflowCore + NextStepId: Step3.2.2 + CancelCondition: data.Flag2 + Inputs: + EventName: '"Event1"' + EventKey: '"Key1"' + EffectiveDate: DateTime.Now + - Id: Step3.2.2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter5 + Outputs: + Counter5: step.Value +- Id: Step4 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter6 + Outputs: + Counter6: step.Value diff --git a/test/WorkflowCore.Testing/JsonWorkflowTest.cs b/test/WorkflowCore.Testing/JsonWorkflowTest.cs index 0f15505cd..78f36eae8 100644 --- a/test/WorkflowCore.Testing/JsonWorkflowTest.cs +++ b/test/WorkflowCore.Testing/JsonWorkflowTest.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; +using WorkflowCore.Services.DefinitionStorage; namespace WorkflowCore.Testing { @@ -55,7 +56,7 @@ protected virtual void ConfigureServices(IServiceCollection services) public string StartWorkflow(string json, object data) { - var def = DefinitionLoader.LoadDefinition(json); + var def = DefinitionLoader.LoadDefinition(json, Deserializers.Json); var workflowId = Host.StartWorkflow(def.Id, data).Result; return workflowId; } diff --git a/test/WorkflowCore.Testing/YamlWorkflowTest.cs b/test/WorkflowCore.Testing/YamlWorkflowTest.cs new file mode 100644 index 000000000..6bd524e60 --- /dev/null +++ b/test/WorkflowCore.Testing/YamlWorkflowTest.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Services.DefinitionStorage; + +namespace WorkflowCore.Testing +{ + public abstract class YamlWorkflowTest : IDisposable + { + protected IWorkflowHost Host; + protected IPersistenceProvider PersistenceProvider; + protected IDefinitionLoader DefinitionLoader; + protected List UnhandledStepErrors = new List(); + + protected virtual void Setup() + { + //setup dependency injection + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + ConfigureServices(services); + + var serviceProvider = services.BuildServiceProvider(); + + //config logging + var loggerFactory = serviceProvider.GetService(); + //loggerFactory.AddConsole(LogLevel.Debug); + + PersistenceProvider = serviceProvider.GetService(); + DefinitionLoader = serviceProvider.GetService(); + Host = serviceProvider.GetService(); + Host.OnStepError += Host_OnStepError; + Host.Start(); + } + + private void Host_OnStepError(WorkflowInstance workflow, WorkflowStep step, Exception exception) + { + UnhandledStepErrors.Add(new StepError() + { + Exception = exception, + Step = step, + Workflow = workflow + }); + } + + protected virtual void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(); + } + + public string StartWorkflow(string json, object data) + { + var def = DefinitionLoader.LoadDefinition(json, Deserializers.Yaml); + var workflowId = Host.StartWorkflow(def.Id, data).Result; + return workflowId; + } + + protected void WaitForWorkflowToComplete(string workflowId, TimeSpan timeOut) + { + var status = GetStatus(workflowId); + var counter = 0; + while ((status == WorkflowStatus.Runnable) && (counter < (timeOut.TotalMilliseconds / 100))) + { + Thread.Sleep(100); + counter++; + status = GetStatus(workflowId); + } + } + + protected IEnumerable GetActiveSubscriptons(string eventName, string eventKey) + { + return PersistenceProvider.GetSubcriptions(eventName, eventKey, DateTime.MaxValue).Result; + } + + protected void WaitForEventSubscription(string eventName, string eventKey, TimeSpan timeOut) + { + var counter = 0; + while ((!GetActiveSubscriptons(eventName, eventKey).Any()) && (counter < (timeOut.TotalMilliseconds / 100))) + { + Thread.Sleep(100); + counter++; + } + } + + protected WorkflowStatus GetStatus(string workflowId) + { + var instance = PersistenceProvider.GetWorkflowInstance(workflowId).Result; + return instance.Status; + } + + protected TData GetData(string workflowId) + { + var instance = PersistenceProvider.GetWorkflowInstance(workflowId).Result; + return (TData)instance.Data; + } + + public void Dispose() + { + Host.Stop(); + } + } + +} diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index bc41b01d9..884e2937e 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -27,7 +27,7 @@ - + diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs index 99a9b49ce..03494c5de 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs @@ -29,7 +29,7 @@ public DefinitionLoaderTests() [Fact(DisplayName = "Should register workflow")] public void RegisterDefinition() { - _subject.LoadDefinition("{\"Id\": \"HelloWorld\", \"Version\": 1, \"Steps\": []}"); + _subject.LoadDefinition("{\"Id\": \"HelloWorld\", \"Version\": 1, \"Steps\": []}", Deserializers.Json); A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Id == "HelloWorld"))).MustHaveHappened(); A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Version == 1))).MustHaveHappened(); @@ -39,7 +39,7 @@ public void RegisterDefinition() [Fact(DisplayName = "Should parse definition")] public void ParseDefinition() { - _subject.LoadDefinition(TestAssets.Utils.GetTestDefinitionJson()); + _subject.LoadDefinition(TestAssets.Utils.GetTestDefinitionJson(), Deserializers.Json); A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Id == "Test"))).MustHaveHappened(); A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Version == 1))).MustHaveHappened(); @@ -51,7 +51,7 @@ public void ParseDefinition() [Fact(DisplayName = "Should parse definition")] public void ParseDefinitionDynamic() { - _subject.LoadDefinition(TestAssets.Utils.GetTestDefinitionDynamicJson()); + _subject.LoadDefinition(TestAssets.Utils.GetTestDefinitionDynamicJson(), Deserializers.Json); A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Id == "Test"))).MustHaveHappened(); A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Version == 1))).MustHaveHappened();