From 96b4b82c30e5564afa84da21d324b8efc233e60a Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 12 Jun 2017 20:50:48 -0700 Subject: [PATCH 1/5] delay step --- src/WorkflowCore/Interface/IStepBuilder.cs | 14 ++++++++++++ src/WorkflowCore/Primitives/Delay.cs | 22 +++++++++++++++++++ src/WorkflowCore/Services/StepBuilder.cs | 21 ++++++++++++++++++ src/WorkflowCore/WorkflowCore.csproj | 8 +++---- .../WorkflowCore.LockProviders.Redlock.csproj | 2 +- .../WorkflowCore.LockProviders.ZeroMQ.csproj | 2 +- ...lowCore.Persistence.EntityFramework.csproj | 9 ++------ .../WorkflowCore.Persistence.MongoDB.csproj | 12 ++++------ ...WorkflowCore.Persistence.PostgreSQL.csproj | 13 ++++------- .../WorkflowCore.Persistence.SqlServer.csproj | 13 ++++------- .../WorkflowCore.Persistence.Sqlite.csproj | 13 ++++------- .../WorkflowCore.Providers.Azure.csproj | 7 +----- ...orkflowCore.QueueProviders.RabbitMQ.csproj | 9 ++------ .../WorkflowCore.QueueProviders.ZeroMQ.csproj | 13 ++++------- 14 files changed, 88 insertions(+), 70 deletions(-) create mode 100644 src/WorkflowCore/Primitives/Delay.cs diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index c70b7af59..649d8cf6f 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -76,11 +76,18 @@ public interface IStepBuilder /// /// /// + /// /// IStepBuilder WaitFor(string eventName, Expression> eventKey, Expression> effectiveDate = null); IStepBuilder End(string name) where TStep : IStepBody; + /// + /// Configure the behavior when this step throws an unhandled exception + /// + /// + /// + /// IStepBuilder OnError(WorkflowErrorHandling behavior, TimeSpan? retryInterval = null); /// @@ -89,6 +96,13 @@ public interface IStepBuilder /// IStepBuilder EndWorkflow(); + /// + /// Wait for a specified period + /// + /// + /// + IStepBuilder Delay(Expression> period); + IContainerStepBuilder ForEach(Expression> collection); IContainerStepBuilder While(Expression> condition); diff --git a/src/WorkflowCore/Primitives/Delay.cs b/src/WorkflowCore/Primitives/Delay.cs new file mode 100644 index 000000000..a8062e2d4 --- /dev/null +++ b/src/WorkflowCore/Primitives/Delay.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Primitives +{ + public class Delay : StepBody + { + public TimeSpan Period { get; set; } + + public override ExecutionResult Run(IStepExecutionContext context) + { + if (context.PersistenceData != null) + return ExecutionResult.Next(); + + return ExecutionResult.Sleep(Period, true); + } + } +} diff --git a/src/WorkflowCore/Services/StepBuilder.cs b/src/WorkflowCore/Services/StepBuilder.cs index 5fac10ba8..e251ef44f 100644 --- a/src/WorkflowCore/Services/StepBuilder.cs +++ b/src/WorkflowCore/Services/StepBuilder.cs @@ -150,6 +150,27 @@ public IStepBuilder EndWorkflow() return this; } + public IStepBuilder Delay(Expression> period) + { + var newStep = new WorkflowStep(); + + Expression> inputExpr = (x => x.Period); + + var mapping = new DataMapping() + { + Source = period, + Target = inputExpr + }; + newStep.Inputs.Add(mapping); + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + + Step.Outcomes.Add(new StepOutcome() { NextStep = newStep.Id }); + + return stepBuilder; + } + public IContainerStepBuilder ForEach(Expression> collection) { var newStep = new WorkflowStep(); diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 43b3fb2fa..92a0285cf 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -4,7 +4,7 @@ Workflow Core 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore WorkflowCore workflow;.NET;Core;state machine @@ -18,9 +18,9 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 1.2.7 - 1.2.7.0 - 1.2.7.0 + 1.2.8 + 1.2.8.0 + 1.2.8.0 diff --git a/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj b/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj index e8abbe462..9bd364284 100644 --- a/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj +++ b/src/providers/WorkflowCore.LockProviders.Redlock/WorkflowCore.LockProviders.Redlock.csproj @@ -4,7 +4,7 @@ Workflow Core Redlock distributed lock manager 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.LockProviders.Redlock WorkflowCore.LockProviders.Redlock workflow;.NET;Core;state machine;WorkflowCore;Redlock diff --git a/src/providers/WorkflowCore.LockProviders.ZeroMQ/WorkflowCore.LockProviders.ZeroMQ.csproj b/src/providers/WorkflowCore.LockProviders.ZeroMQ/WorkflowCore.LockProviders.ZeroMQ.csproj index e7c3a5355..ca8756e8b 100644 --- a/src/providers/WorkflowCore.LockProviders.ZeroMQ/WorkflowCore.LockProviders.ZeroMQ.csproj +++ b/src/providers/WorkflowCore.LockProviders.ZeroMQ/WorkflowCore.LockProviders.ZeroMQ.csproj @@ -4,7 +4,7 @@ Workflow Core 0MQ distributed lock manager 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.LockProviders.ZeroMQ WorkflowCore.LockProviders.ZeroMQ workflow;.NET;Core;state machine;WorkflowCore;0MQ diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 77ecc4133..f51c56f4b 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -4,7 +4,7 @@ Workflow Core EntityFramework Core Persistence Provider 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore @@ -17,7 +17,7 @@ false false false - 1.2.7 + 1.2.8 Base package for Workflow-core peristence providers using entity framework @@ -31,9 +31,4 @@ - - - - - diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 6119eb42f..43b81ede5 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -4,7 +4,7 @@ Workflow Core MongoDB Persistence Provider 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.Persistence.MongoDB WorkflowCore.Persistence.MongoDB workflow;.NET;Core;state machine;WorkflowCore;MongoDB;Mongo @@ -17,10 +17,10 @@ false false false - 1.2.7 + 1.2.8 Provides support to persist workflows running on Workflow Core to a MongoDB database. - 1.2.7.0 - 1.2.7.0 + 1.2.8.0 + 1.2.8.0 @@ -37,9 +37,5 @@ - - - - diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index b3669cca1..5d8f8fb35 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -4,7 +4,7 @@ Workflow Core PostgreSQL Persistence Provider 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.Persistence.PostgreSQL WorkflowCore.Persistence.PostgreSQL workflow;.NET;Core;state machine;WorkflowCore;PostgreSQL @@ -18,9 +18,9 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 1.2.4 - 1.2.4.0 - 1.2.4.0 + 1.2.8 + 1.2.8.0 + 1.2.8.0 @@ -38,11 +38,6 @@ - - - - - diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 9b468fd9e..51f3820ec 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -17,10 +17,10 @@ false false false - 1.2.4 + 1.2.8 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 1.2.4.0 - 1.2.4.0 + 1.2.8.0 + 1.2.8.0 @@ -36,11 +36,6 @@ - - - - - diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 5dac71a6b..6c861ba20 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -18,9 +18,9 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 1.2.4 - 1.2.4.0 - 1.2.4.0 + 1.2.8 + 1.2.8.0 + 1.2.8.0 @@ -32,9 +32,4 @@ - - - - - diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index 6ebd1ff5e..e2aa671e6 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -1,7 +1,7 @@  - netstandard1.3;net452 + netstandard1.3 Azure providers for Workflow Core - Provides distributed lock management on Workflow Core @@ -24,9 +24,4 @@ - - - - - \ No newline at end of file diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index 5f9eb0f1e..3acbfeb63 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;net452 + netstandard1.3 WorkflowCore.QueueProviders.RabbitMQ WorkflowCore.QueueProviders.RabbitMQ workflow;.NET;Core;state machine;WorkflowCore;RabbitMQ @@ -17,7 +17,7 @@ false false false - 1.2.7 + 1.2.8 Queue provider for Workflow-core using RabbitMQ @@ -30,9 +30,4 @@ - - - - - diff --git a/src/providers/WorkflowCore.QueueProviders.ZeroMQ/WorkflowCore.QueueProviders.ZeroMQ.csproj b/src/providers/WorkflowCore.QueueProviders.ZeroMQ/WorkflowCore.QueueProviders.ZeroMQ.csproj index d70202fa9..b92f69b5f 100644 --- a/src/providers/WorkflowCore.QueueProviders.ZeroMQ/WorkflowCore.QueueProviders.ZeroMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.ZeroMQ/WorkflowCore.QueueProviders.ZeroMQ.csproj @@ -4,7 +4,7 @@ Workflow Core ZeroMQ queue provider 1.1.0 Daniel Gerlag - netstandard1.3;net452 + netstandard1.3 WorkflowCore.QueueProviders.ZeroMQ WorkflowCore.QueueProviders.ZeroMQ workflow;.NET;Core;state machine;WorkflowCore;ZeroMQ;0MQ @@ -17,9 +17,9 @@ false false false - 1.2.7 - 1.2.7.0 - 1.2.7.0 + 1.2.8 + 1.2.8.0 + 1.2.8.0 @@ -31,9 +31,4 @@ - - - - - From cdecaa485c20b2224d09a28bd12b539ec1439ba7 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 13 Jun 2017 07:46:33 -0700 Subject: [PATCH 2/5] context in input parameters --- src/WorkflowCore/Interface/IStepBuilder.cs | 9 +++++++ src/WorkflowCore/Services/StepBuilder.cs | 9 +++++++ src/WorkflowCore/Services/WorkflowExecutor.cs | 24 +++++++++++++++---- .../WorkflowCore.Sample09/ForEachWorkflow.cs | 1 + .../Steps/DisplayContext.cs | 5 +++- 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index 649d8cf6f..e9cd86929 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -62,6 +62,15 @@ public interface IStepBuilder /// IStepBuilder Input(Expression> stepProperty, Expression> value); + /// + /// Map properties on the step to properties on the workflow data object before the step executes + /// + /// + /// + /// + /// + IStepBuilder Input(Expression> stepProperty, Expression> value); + /// /// Map properties on the workflow data object to properties on the step after the step executes /// diff --git a/src/WorkflowCore/Services/StepBuilder.cs b/src/WorkflowCore/Services/StepBuilder.cs index e251ef44f..5919822e1 100644 --- a/src/WorkflowCore/Services/StepBuilder.cs +++ b/src/WorkflowCore/Services/StepBuilder.cs @@ -82,6 +82,15 @@ public IStepBuilder Input(Expression Input(Expression> stepProperty, Expression> value) + { + var mapping = new DataMapping(); + mapping.Source = value; + mapping.Target = stepProperty; + Step.Inputs.Add(mapping); + return this; + } + public IStepBuilder Output(Expression> dataProperty, Expression> value) { var mapping = new DataMapping(); diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index bf63fa18b..60cf6eafa 100644 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -75,9 +75,7 @@ public WorkflowExecutorResult Execute(WorkflowInstance workflow, WorkflowOptions }); continue; } - - ProcessInputs(workflow, step, body); - + IStepExecutionContext context = new StepExecutionContext() { Workflow = workflow, @@ -87,6 +85,8 @@ public WorkflowExecutorResult Execute(WorkflowInstance workflow, WorkflowOptions Item = pointer.ContextItem }; + ProcessInputs(workflow, step, body, context); + switch (step.BeforeExecute(wfResult, context, pointer, body)) { case ExecutionPipelineDirective.Defer: @@ -198,12 +198,26 @@ private void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinitio } } - private void ProcessInputs(WorkflowInstance workflow, WorkflowStep step, IStepBody body) + private void ProcessInputs(WorkflowInstance workflow, WorkflowStep step, IStepBody body, IStepExecutionContext context) { + //TODO: Move to own class foreach (var input in step.Inputs) { var member = (input.Target.Body as MemberExpression); - var resolvedValue = input.Source.Compile().DynamicInvoke(workflow.Data); + object resolvedValue = null; + + switch (input.Source.Parameters.Count) + { + case 1: + resolvedValue = input.Source.Compile().DynamicInvoke(workflow.Data); + break; + case 2: + resolvedValue = input.Source.Compile().DynamicInvoke(workflow.Data, context); + break; + default: + throw new ArgumentException(); + } + step.BodyType.GetProperty(member.Member.Name).SetValue(body, resolvedValue); } } diff --git a/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs b/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs index dcd9a5e22..4e525c3de 100644 --- a/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs +++ b/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs @@ -18,6 +18,7 @@ public void Build(IWorkflowBuilder builder) .ForEach(data => new List() { 1, 2, 3, 4 }) .Do(x => x .StartWith() + .Input(step => step.Item, (data, context) => context.Item) .Then()) .Then(); } diff --git a/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs b/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs index e6cdb1c68..9782a32bc 100644 --- a/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs +++ b/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs @@ -8,9 +8,12 @@ namespace WorkflowCore.Sample09 { public class DisplayContext : StepBody { + + public object Item { get; set; } + public override ExecutionResult Run(IStepExecutionContext context) { - Console.WriteLine($"Working on item {context.Item}"); + Console.WriteLine($"Working on item {Item}"); return ExecutionResult.Next(); } } From 4cab84e2633caa64933f7a1f069157a26f53a9aa Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 14 Jun 2017 18:22:03 -0700 Subject: [PATCH 3/5] schedule step --- src/WorkflowCore/Interface/IStepBuilder.cs | 9 +++++ .../Interface/IWorkflowBuilder.cs | 2 + .../Models/SchedulePersistenceData.cs | 12 ++++++ src/WorkflowCore/Primitives/ActionStepBody.cs | 21 ++++++++++ src/WorkflowCore/Primitives/Schedule.cs | 39 +++++++++++++++++++ src/WorkflowCore/Services/StepBuilder.cs | 33 +++++++++++++++- src/WorkflowCore/Services/WorkflowBuilder.cs | 9 +++++ src/samples/WorkflowCore.Sample01/Program.cs | 1 + 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/WorkflowCore/Models/SchedulePersistenceData.cs create mode 100644 src/WorkflowCore/Primitives/ActionStepBody.cs create mode 100644 src/WorkflowCore/Primitives/Schedule.cs diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index e9cd86929..677ed89ad 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -45,6 +45,13 @@ public interface IStepBuilder /// IStepBuilder Then(Func body); + /// + /// Specify an inline next step in the workflow + /// + /// + /// + IStepBuilder Then(Action body); + /// /// Configure an outcome for this step, then wire it to another step /// @@ -126,5 +133,7 @@ public interface IStepBuilder IContainerStepBuilder When(Expression> outcomeValue, string label = null); IParallelStepBuilder Parallel(); + + IContainerStepBuilder Schedule(Expression> time); } } \ No newline at end of file diff --git a/src/WorkflowCore/Interface/IWorkflowBuilder.cs b/src/WorkflowCore/Interface/IWorkflowBuilder.cs index f23a96009..97be74597 100644 --- a/src/WorkflowCore/Interface/IWorkflowBuilder.cs +++ b/src/WorkflowCore/Interface/IWorkflowBuilder.cs @@ -24,6 +24,8 @@ public interface IWorkflowBuilder : IWorkflowBuilder IStepBuilder StartWith(Func body); + IStepBuilder StartWith(Action body); + IEnumerable GetUpstreamSteps(int id); IWorkflowBuilder UseDefaultErrorBehavior(WorkflowErrorHandling behavior, TimeSpan? retryInterval = null); diff --git a/src/WorkflowCore/Models/SchedulePersistenceData.cs b/src/WorkflowCore/Models/SchedulePersistenceData.cs new file mode 100644 index 000000000..8ac17fcb0 --- /dev/null +++ b/src/WorkflowCore/Models/SchedulePersistenceData.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace WorkflowCore.Models +{ + public class SchedulePersistenceData + { + public bool Elapsed { get; set; } + + } +} diff --git a/src/WorkflowCore/Primitives/ActionStepBody.cs b/src/WorkflowCore/Primitives/ActionStepBody.cs new file mode 100644 index 000000000..ec84df011 --- /dev/null +++ b/src/WorkflowCore/Primitives/ActionStepBody.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Primitives +{ + public class ActionStepBody : StepBody + { + public Action Body { get; set; } + + public override ExecutionResult Run(IStepExecutionContext context) + { + Body(context); + return ExecutionResult.Next(); + } + } +} diff --git a/src/WorkflowCore/Primitives/Schedule.cs b/src/WorkflowCore/Primitives/Schedule.cs new file mode 100644 index 000000000..ef69d71df --- /dev/null +++ b/src/WorkflowCore/Primitives/Schedule.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Primitives +{ + public class Schedule : ContainerStepBody + { + public TimeSpan Period { get; set; } + + public override ExecutionResult Run(IStepExecutionContext context) + { + if (context.PersistenceData == null) + return ExecutionResult.Sleep(Period, new SchedulePersistenceData() { Elapsed = false }); + + + if (context.PersistenceData is SchedulePersistenceData) + { + if (!((SchedulePersistenceData) context.PersistenceData).Elapsed) + return ExecutionResult.Branch(new List() { null }, new SchedulePersistenceData() { Elapsed = true }); + + var complete = true; + + foreach (var childId in context.ExecutionPointer.Children) + complete = complete && IsBranchComplete(context.Workflow.ExecutionPointers, childId); + + if (complete) + return ExecutionResult.Next(); + + return ExecutionResult.Persist(context.PersistenceData); + } + + throw new ArgumentException(); + } + } +} diff --git a/src/WorkflowCore/Services/StepBuilder.cs b/src/WorkflowCore/Services/StepBuilder.cs index 5919822e1..353ec971f 100644 --- a/src/WorkflowCore/Services/StepBuilder.cs +++ b/src/WorkflowCore/Services/StepBuilder.cs @@ -63,6 +63,16 @@ public IStepBuilder Then(Func Then(Action body) + { + var newStep = new WorkflowStep(); + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + stepBuilder.Input(x => x.Body, x => body); + Step.Outcomes.Add(new StepOutcome() { NextStep = newStep.Id }); + return stepBuilder; + } + public IStepOutcomeBuilder When(object outcomeValue, string label = null) { StepOutcome result = new StepOutcome(); @@ -274,7 +284,7 @@ public IContainerStepBuilder When(Expression(WorkflowBuilder, newStep, switchBuilder); - + switchBuilder.Step.Children.Add(newStep.Id); return stepBuilder; @@ -292,6 +302,27 @@ public IParallelStepBuilder Parallel() return stepBuilder; } + public IContainerStepBuilder Schedule(Expression> time) + { + var newStep = new WorkflowStep(); + + Expression> inputExpr = (x => x.Period); + + var mapping = new DataMapping() + { + Source = time, + Target = inputExpr + }; + newStep.Inputs.Add(mapping); + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new SkipStepBuilder(WorkflowBuilder, newStep, this); + + Step.Outcomes.Add(new StepOutcome() { NextStep = newStep.Id }); + + return stepBuilder; + } + public IStepBuilder Do(Action> builder) { builder.Invoke(WorkflowBuilder); diff --git a/src/WorkflowCore/Services/WorkflowBuilder.cs b/src/WorkflowCore/Services/WorkflowBuilder.cs index af6793a28..436ff6a0d 100644 --- a/src/WorkflowCore/Services/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/WorkflowBuilder.cs @@ -82,6 +82,15 @@ public IStepBuilder StartWith(Func StartWith(Action body) + { + var newStep = new WorkflowStep(); + AddStep(newStep); + var stepBuilder = new StepBuilder(this, newStep); + stepBuilder.Input(x => x.Body, x => body); + return stepBuilder; + } + public IEnumerable GetUpstreamSteps(int id) { return Steps.Where(x => x.Outcomes.Any(y => y.NextStep == id)).ToList(); diff --git a/src/samples/WorkflowCore.Sample01/Program.cs b/src/samples/WorkflowCore.Sample01/Program.cs index 20e5a6795..2f1e6105c 100644 --- a/src/samples/WorkflowCore.Sample01/Program.cs +++ b/src/samples/WorkflowCore.Sample01/Program.cs @@ -34,6 +34,7 @@ private static IServiceProvider ConfigureServices() IServiceCollection services = new ServiceCollection(); services.AddLogging(); services.AddWorkflow(); + //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); services.AddTransient(); var serviceProvider = services.BuildServiceProvider(); From 92c4ca6ebb0d1604ea9e2ab5737acbee2fced062 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 17 Jun 2017 05:37:02 -0700 Subject: [PATCH 4/5] samples docs --- ReleaseNotes/1.2.8.md | 23 ++++++++++++++++++++ WorkflowCore.sln | 4 +++- src/WorkflowCore/Interface/IStepBuilder.cs | 24 +++++++++++++++++++++ src/samples/WorkflowCore.Sample09/README.md | 15 ++----------- 4 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 ReleaseNotes/1.2.8.md diff --git a/ReleaseNotes/1.2.8.md b/ReleaseNotes/1.2.8.md new file mode 100644 index 000000000..146d68d0a --- /dev/null +++ b/ReleaseNotes/1.2.8.md @@ -0,0 +1,23 @@ +# Workflow Core 1.2.8 + +* Added .Schedule() API, to future date a block of steps to run in parallel to the rest of the workflow. + +This following example will execute the block of steps after 3 days +```c# +builder + .StartWith() + .Schedule(data => TimeSpan.FromDays(3)).Do(block => + block.StartWith() + .Then()) + .Then(); +``` + +* Added inline action steps API + +```c# +builder + .StartWith(context => Console.WriteLine("Hello!")) + .Then(context => Console.WriteLine("Bye!")); +``` + +* Discontinued support for .NET 4.5.2 (.NET 4.6 is .NET Standard 1.3 compatible) diff --git a/WorkflowCore.sln b/WorkflowCore.sln index a3e01ff65..5d8644b17 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +VisualStudioVersion = 15.0.26430.12 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF47161E-E399-451C-BDE8-E92AAD3BD761}" EndProject @@ -88,6 +88,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Sample13", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Providers.Azure", "src\providers\WorkflowCore.Providers.Azure\WorkflowCore.Providers.Azure.csproj", "{A2374B7C-4198-40B3-B8FE-FAC3DB3F2539}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNotes", "{38ECB00C-3F3B-4442-8408-ACE3B37FFAA8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index 677ed89ad..6c72c14b5 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -119,10 +119,25 @@ public interface IStepBuilder /// IStepBuilder Delay(Expression> period); + /// + /// Execute a block of steps, once for each item in a collection in a parallel foreach + /// + /// + /// IContainerStepBuilder ForEach(Expression> collection); + /// + /// Repeat a block of steps until a condition becomes true + /// + /// + /// IContainerStepBuilder While(Expression> condition); + /// + /// Execute a block of steps if a condition is true + /// + /// + /// IContainerStepBuilder If(Expression> condition); /// @@ -132,8 +147,17 @@ public interface IStepBuilder /// IContainerStepBuilder When(Expression> outcomeValue, string label = null); + /// + /// Execute multiple blocks of steps in parallel + /// + /// IParallelStepBuilder Parallel(); + /// + /// Schedule a block of steps to execute in parallel sometime in the future + /// + /// + /// IContainerStepBuilder Schedule(Expression> time); } } \ No newline at end of file diff --git a/src/samples/WorkflowCore.Sample09/README.md b/src/samples/WorkflowCore.Sample09/README.md index 3af2576af..9c7b54bc8 100644 --- a/src/samples/WorkflowCore.Sample09/README.md +++ b/src/samples/WorkflowCore.Sample09/README.md @@ -9,6 +9,7 @@ builder .ForEach(data => new List() { 1, 2, 3, 4 }) .Do(x => x .StartWith() + .Input(step => step.Item, (data, context) => context.Item) .Then()) .Then(); ``` @@ -21,20 +22,8 @@ builder .ForEach(data => data.MyCollection) .Do(x => x .StartWith() + .Input(step => step.Item, (data, context) => context.Item) .Then()) .Then(); ``` - -Access the iteration item from the step execution context - -```c# -public class DisplayContext : StepBody -{ - public override ExecutionResult Run(IStepExecutionContext context) - { - Console.WriteLine($"Working on item {context.Item}"); - return ExecutionResult.Next(); - } -} -``` From f4a3bd92b3312b585827fc92f43bb252d7c5888a Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 17 Jun 2017 06:24:27 -0700 Subject: [PATCH 5/5] docs --- ReleaseNotes/1.2.8.md | 24 ++++++++++++++++++++++-- WorkflowCore.sln | 3 +++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/ReleaseNotes/1.2.8.md b/ReleaseNotes/1.2.8.md index 146d68d0a..f075fdb2e 100644 --- a/ReleaseNotes/1.2.8.md +++ b/ReleaseNotes/1.2.8.md @@ -1,6 +1,6 @@ # Workflow Core 1.2.8 -* Added .Schedule() API, to future date a block of steps to run in parallel to the rest of the workflow. +* .Schedule() API, to future date a block of steps to run in parallel to the rest of the workflow. This following example will execute the block of steps after 3 days ```c# @@ -12,7 +12,27 @@ builder .Then(); ``` -* Added inline action steps API +* Overload of the .Input() method to allow access to the context object + +```c# +builder + .StartWith() + .ForEach(data => new List() { 1, 2, 3, 4 }) + .Do(x => x + .StartWith() + .Input(step => step.Item, (data, context) => context.Item) + .Then()) + .Then(); +``` + +```c# +builder + .StartWith(context => Console.WriteLine("Hello!")) + .Then(context => Console.WriteLine("Bye!")); +``` + + +* Inline action steps API ```c# builder diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 5d8644b17..f685f2c8b 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -89,6 +89,9 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Providers.Azure", "src\providers\WorkflowCore.Providers.Azure\WorkflowCore.Providers.Azure.csproj", "{A2374B7C-4198-40B3-B8FE-FAC3DB3F2539}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNotes", "{38ECB00C-3F3B-4442-8408-ACE3B37FFAA8}" + ProjectSection(SolutionItems) = preProject + ReleaseNotes\1.2.8.md = ReleaseNotes\1.2.8.md + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution