Skip to content

Commit 5c4d57b

Browse files
authored
Merge pull request danielgerlag#30 from danielgerlag/endstep
Control structures
2 parents 674174b + 062eba5 commit 5c4d57b

File tree

131 files changed

+2814
-1846
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+2814
-1846
lines changed

WorkflowCore.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26206.0
4+
VisualStudioVersion = 15.0.26228.4
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF47161E-E399-451C-BDE8-E92AAD3BD761}"
77
EndProject
@@ -74,6 +74,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample08", "sr
7474
EndProject
7575
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.WebAPI", "src\extensions\WorkflowCore.WebAPI\WorkflowCore.WebAPI.csproj", "{FBF8D151-A3BF-4EB3-8F80-D71618696362}"
7676
EndProject
77+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample09", "src\samples\WorkflowCore.Sample09\WorkflowCore.Sample09.csproj", "{50E1AFAC-0B58-43A8-8F03-3A63AAC681FA}"
78+
EndProject
79+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample10", "src\samples\WorkflowCore.Sample10\WorkflowCore.Sample10.csproj", "{5E792455-4C4C-460F-849E-50A5DCED454D}"
80+
EndProject
7781
Global
7882
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7983
Debug|Any CPU = Debug|Any CPU
@@ -192,6 +196,14 @@ Global
192196
{FBF8D151-A3BF-4EB3-8F80-D71618696362}.Debug|Any CPU.Build.0 = Debug|Any CPU
193197
{FBF8D151-A3BF-4EB3-8F80-D71618696362}.Release|Any CPU.ActiveCfg = Release|Any CPU
194198
{FBF8D151-A3BF-4EB3-8F80-D71618696362}.Release|Any CPU.Build.0 = Release|Any CPU
199+
{50E1AFAC-0B58-43A8-8F03-3A63AAC681FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
200+
{50E1AFAC-0B58-43A8-8F03-3A63AAC681FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
201+
{50E1AFAC-0B58-43A8-8F03-3A63AAC681FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
202+
{50E1AFAC-0B58-43A8-8F03-3A63AAC681FA}.Release|Any CPU.Build.0 = Release|Any CPU
203+
{5E792455-4C4C-460F-849E-50A5DCED454D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
204+
{5E792455-4C4C-460F-849E-50A5DCED454D}.Debug|Any CPU.Build.0 = Debug|Any CPU
205+
{5E792455-4C4C-460F-849E-50A5DCED454D}.Release|Any CPU.ActiveCfg = Release|Any CPU
206+
{5E792455-4C4C-460F-849E-50A5DCED454D}.Release|Any CPU.Build.0 = Release|Any CPU
195207
EndGlobalSection
196208
GlobalSection(SolutionProperties) = preSolution
197209
HideSolutionNode = FALSE
@@ -228,5 +240,7 @@ Global
228240
{4C4DE624-9D91-484F-8BF7-2D71264EAB8B} = {6803696C-B19A-4B27-9193-082A02B6F205}
229241
{ED5074AF-A09E-4357-A419-FE3476C0FAE7} = {5080DB09-CBE8-4C45-9957-C3BB7651755E}
230242
{FBF8D151-A3BF-4EB3-8F80-D71618696362} = {6803696C-B19A-4B27-9193-082A02B6F205}
243+
{50E1AFAC-0B58-43A8-8F03-3A63AAC681FA} = {5080DB09-CBE8-4C45-9957-C3BB7651755E}
244+
{5E792455-4C4C-460F-849E-50A5DCED454D} = {5080DB09-CBE8-4C45-9957-C3BB7651755E}
231245
EndGlobalSection
232246
EndGlobal
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace WorkflowCore.Interface
6+
{
7+
public interface IParentStepBuilder<TData, TStepBody>
8+
where TStepBody : IStepBody
9+
{
10+
IStepBuilder<TData, TStepBody> Do(Action<IWorkflowBuilder<TData>> builder);
11+
}
12+
}

src/WorkflowCore/Interface/IPersistenceProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public interface IPersistenceProvider
4040

4141
Task MarkEventUnprocessed(string id);
4242

43+
Task PersistErrors(IEnumerable<ExecutionError> errors);
44+
4345
void EnsureStoreExists();
4446

4547
}

src/WorkflowCore/Interface/IStepBuilder.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections;
23
using System.Linq.Expressions;
34
using WorkflowCore.Interface;
45
using WorkflowCore.Models;
@@ -79,5 +80,15 @@ public interface IStepBuilder<TData, TStepBody>
7980
IStepBuilder<TData, TStep> End<TStep>(string name) where TStep : IStepBody;
8081

8182
IStepBuilder<TData, TStepBody> OnError(WorkflowErrorHandling behavior, TimeSpan? retryInterval = null);
83+
84+
/// <summary>
85+
/// Ends the workflow and marks it as complete
86+
/// </summary>
87+
/// <returns></returns>
88+
//IStepBuilder<TData, TStepBody> EndWorkflow();
89+
90+
IParentStepBuilder<TData, Foreach> ForEach(Expression<Func<TData, IEnumerable>> collection);
91+
92+
IParentStepBuilder<TData, While> While(Expression<Func<TData, bool>> condition);
8293
}
8394
}

src/WorkflowCore/Interface/IStepExecutionContext.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ namespace WorkflowCore.Interface
55
{
66
public interface IStepExecutionContext
77
{
8+
object Item { get; set; }
9+
ExecutionPointer ExecutionPointer { get; set; }
810
object PersistenceData { get; set; }
911
WorkflowStep Step { get; set; }
10-
WorkflowInstance Workflow { get; set; }
12+
WorkflowInstance Workflow { get; set; }
1113
}
1214
}

src/WorkflowCore/Interface/IStepOutcomeBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public interface IStepOutcomeBuilder<TData>
1212
IStepBuilder<TData, TStep> Then<TStep>(Action<IStepBuilder<TData, TStep>> stepSetup = null) where TStep : IStepBody;
1313
IStepBuilder<TData, TStep> Then<TStep>(IStepBuilder<TData, TStep> step) where TStep : IStepBody;
1414
IStepBuilder<TData, InlineStepBody> Then(Func<IStepExecutionContext, ExecutionResult> body);
15+
void EndWorkflow();
1516
}
1617

1718
}

src/WorkflowCore/Interface/IWorkflowExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ namespace WorkflowCore.Interface
66
{
77
public interface IWorkflowExecutor
88
{
9-
Task Execute(WorkflowInstance workflow, IPersistenceProvider persistenceStore, WorkflowOptions options);
9+
WorkflowExecutorResult Execute(WorkflowInstance workflow, WorkflowOptions options);
1010
}
1111
}

src/WorkflowCore/Interface/IWorkflowHost.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ public interface IWorkflowHost
1515
Task<string> StartWorkflow(string workflowId, int? version, object data = null);
1616
Task<string> StartWorkflow<TData>(string workflowId, TData data = null) where TData : class;
1717
Task<string> StartWorkflow<TData>(string workflowId, int? version, TData data = null) where TData : class;
18-
19-
20-
Task SubscribeEvent(string workflowId, int stepId, string eventName, string eventKey, DateTime asOf);
18+
2119
Task PublishEvent(string eventName, string eventKey, object eventData, DateTime? effectiveDate = null);
2220
void RegisterWorkflow<TWorkflow>() where TWorkflow : IWorkflow, new();
2321
void RegisterWorkflow<TWorkflow, TData>() where TWorkflow : IWorkflow<TData>, new() where TData : new();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace WorkflowCore.Models
6+
{
7+
public class ControlPersistenceData
8+
{
9+
public bool ChildrenActive { get; set; }
10+
}
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using WorkflowCore.Interface;
5+
6+
namespace WorkflowCore.Models
7+
{
8+
public class EndStep : WorkflowStep
9+
{
10+
public override Type BodyType => null;
11+
12+
public override ExecutionPipelineDirective InitForExecution(WorkflowExecutorResult executorResult, WorkflowDefinition defintion, WorkflowInstance workflow, ExecutionPointer executionPointer)
13+
{
14+
return ExecutionPipelineDirective.EndWorkflow;
15+
}
16+
}
17+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Linq;
3+
using System.Collections;
4+
using System.Collections.Generic;
5+
using System.Linq.Expressions;
6+
using System.Text;
7+
using WorkflowCore.Interface;
8+
9+
namespace WorkflowCore.Models
10+
{
11+
public class Foreach : StepBody
12+
{
13+
public IEnumerable Collection { get; set; }
14+
15+
public override ExecutionResult Run(IStepExecutionContext context)
16+
{
17+
if (context.PersistenceData == null)
18+
{
19+
var values = Collection.Cast<object>();
20+
return ExecutionResult.Branch(new List<object>(values), new ControlPersistenceData() { ChildrenActive = true });
21+
}
22+
23+
if (context.PersistenceData is ControlPersistenceData)
24+
{
25+
if ((context.PersistenceData as ControlPersistenceData).ChildrenActive)
26+
{
27+
bool complete = true;
28+
foreach (var childId in context.ExecutionPointer.Children)
29+
complete = complete && IsBranchComplete(context.Workflow.ExecutionPointers, childId);
30+
31+
if (complete)
32+
return ExecutionResult.Next();
33+
}
34+
}
35+
36+
return ExecutionResult.Persist(context.PersistenceData);
37+
}
38+
39+
private bool IsBranchComplete(IEnumerable<ExecutionPointer> pointers, string rootId)
40+
{
41+
var root = pointers.First(x => x.Id == rootId);
42+
43+
if (root.EndTime == null)
44+
return false;
45+
46+
var list = pointers.Where(x => x.PredecessorId == rootId).ToList();
47+
48+
bool result = true;
49+
50+
foreach (var item in list)
51+
result = result && IsBranchComplete(pointers, item.Id);
52+
53+
return result;
54+
}
55+
56+
}
57+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Linq;
3+
using System.Collections;
4+
using System.Collections.Generic;
5+
using System.Linq.Expressions;
6+
using System.Text;
7+
using WorkflowCore.Interface;
8+
9+
namespace WorkflowCore.Models
10+
{
11+
public class While : StepBody
12+
{
13+
public bool ConditionResult { get; set; }
14+
15+
public override ExecutionResult Run(IStepExecutionContext context)
16+
{
17+
if (context.PersistenceData == null)
18+
{
19+
if (ConditionResult)
20+
return ExecutionResult.Branch(new List<object>() { null }, new ControlPersistenceData() { ChildrenActive = true });
21+
else
22+
return ExecutionResult.Next();
23+
}
24+
25+
if ((context.PersistenceData is ControlPersistenceData) && ((context.PersistenceData as ControlPersistenceData).ChildrenActive))
26+
{
27+
bool complete = true;
28+
foreach (var childId in context.ExecutionPointer.Children)
29+
complete = complete && IsBranchComplete(context.Workflow.ExecutionPointers, childId);
30+
31+
if (complete)
32+
return ExecutionResult.Persist(null);
33+
else
34+
return ExecutionResult.Persist(context.PersistenceData);
35+
}
36+
37+
throw new Exception("Corrupt persistence data");
38+
}
39+
40+
private bool IsBranchComplete(IEnumerable<ExecutionPointer> pointers, string rootId)
41+
{
42+
var root = pointers.First(x => x.Id == rootId);
43+
44+
if (root.EndTime == null)
45+
return false;
46+
47+
var list = pointers.Where(x => x.PredecessorId == rootId).ToList();
48+
49+
bool result = true;
50+
51+
foreach (var item in list)
52+
result = result && IsBranchComplete(pointers, item.Id);
53+
54+
return result;
55+
}
56+
57+
}
58+
}

src/WorkflowCore/Models/ExecutionError.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ namespace WorkflowCore.Models
77
{
88
public class ExecutionError
99
{
10-
public string Id { get; set; }
11-
1210
public DateTime ErrorTime { get; set; }
1311

12+
public string WorkflowId { get; set; }
13+
14+
public string ExecutionPointerId { get; set; }
15+
1416
public string Message { get; set; }
1517
}
1618
}

src/WorkflowCore/Models/ExecutionPointer.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,19 @@ public class ExecutionPointer
2727

2828
public bool EventPublished { get; set; }
2929

30-
public object EventData { get; set; }
30+
public object EventData { get; set; }
31+
32+
public Dictionary<string, object> ExtensionAttributes { get; set; } = new Dictionary<string, object>();
3133

32-
public int ConcurrentFork { get; set; }
34+
public string StepName { get; set; }
3335

34-
public bool PathTerminator { get; set; }
36+
public int RetryCount { get; set; }
3537

36-
public List<ExecutionError> Errors { get; set; } = new List<ExecutionError>();
37-
38-
public Dictionary<string, object> ExtensionAttributes { get; set; } = new Dictionary<string, object>();
38+
public List<string> Children { get; set; } = new List<string>();
3939

40-
public string StepName { get; set; }
40+
public object ContextItem { get; set; }
41+
42+
public string PredecessorId { get; set; }
4143

4244
}
4345
}

src/WorkflowCore/Models/ExecutionResult.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class ExecutionResult
1515

1616
public object PersistenceData { get; set; }
1717

18+
public List<object> BranchValues { get; set; } = new List<object>();
19+
1820
public ExecutionResult()
1921
{
2022
}
@@ -43,12 +45,22 @@ public static ExecutionResult Next()
4345
};
4446
}
4547

46-
public static ExecutionResult Persist(object value)
48+
public static ExecutionResult Persist(object persistenceData)
4749
{
4850
return new ExecutionResult()
4951
{
5052
Proceed = false,
51-
OutcomeValue = value
53+
PersistenceData = persistenceData
54+
};
55+
}
56+
57+
public static ExecutionResult Branch(List<object> branches, object persistenceData)
58+
{
59+
return new ExecutionResult()
60+
{
61+
Proceed = false,
62+
PersistenceData = persistenceData,
63+
BranchValues = branches
5264
};
5365
}
5466

src/WorkflowCore/Models/StepExecutionContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ public class StepExecutionContext : IStepExecutionContext
1010
{
1111
public WorkflowInstance Workflow { get; set; }
1212
public WorkflowStep Step { get; set; }
13+
public ExecutionPointer ExecutionPointer { get; set; }
1314
public object PersistenceData { get; set; }
15+
public object Item { get; set; }
1416
}
1517
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using WorkflowCore.Interface;
5+
6+
namespace WorkflowCore.Models
7+
{
8+
public class SubWorkflowStepBody : StepBody
9+
{
10+
public override ExecutionResult Run(IStepExecutionContext context)
11+
{
12+
throw new NotImplementedException();
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)