1
+ using System ;
2
+ using System . Linq ;
3
+ using System . Reflection ;
4
+ using System . Threading ;
5
+ using System . Threading . Tasks ;
6
+ using Microsoft . Extensions . Logging ;
7
+ using WorkflowCore . Exceptions ;
8
+ using WorkflowCore . Interface ;
9
+ using WorkflowCore . Models ;
10
+
11
+ namespace WorkflowCore . Services
12
+ {
13
+ public class WorkflowController : IWorkflowController
14
+ {
15
+ private readonly IPersistenceProvider _persistenceStore ;
16
+ private readonly IDistributedLockProvider _lockProvider ;
17
+ private readonly IWorkflowRegistry _registry ;
18
+ private readonly IQueueProvider _queueProvider ;
19
+ private readonly ILogger _logger ;
20
+
21
+
22
+ public WorkflowController ( IPersistenceProvider persistenceStore , IDistributedLockProvider lockProvider , IWorkflowRegistry registry , IQueueProvider queueProvider , ILoggerFactory loggerFactory )
23
+ {
24
+ _persistenceStore = persistenceStore ;
25
+ _lockProvider = lockProvider ;
26
+ _registry = registry ;
27
+ _queueProvider = queueProvider ;
28
+ _logger = loggerFactory . CreateLogger < WorkflowController > ( ) ;
29
+ }
30
+
31
+ public Task < string > StartWorkflow ( string workflowId , object data = null )
32
+ {
33
+ return StartWorkflow ( workflowId , null , data ) ;
34
+ }
35
+
36
+ public Task < string > StartWorkflow ( string workflowId , int ? version , object data = null )
37
+ {
38
+ return StartWorkflow < object > ( workflowId , version , data ) ;
39
+ }
40
+
41
+ public Task < string > StartWorkflow < TData > ( string workflowId , TData data = null )
42
+ where TData : class
43
+ {
44
+ return StartWorkflow < TData > ( workflowId , null , data ) ;
45
+ }
46
+
47
+ public async Task < string > StartWorkflow < TData > ( string workflowId , int ? version , TData data = null )
48
+ where TData : class
49
+ {
50
+
51
+ var def = _registry . GetDefinition ( workflowId , version ) ;
52
+ if ( def == null )
53
+ {
54
+ throw new WorkflowNotRegisteredException ( workflowId , version ) ;
55
+ }
56
+
57
+ var wf = new WorkflowInstance
58
+ {
59
+ WorkflowDefinitionId = workflowId ,
60
+ Version = def . Version ,
61
+ Data = data ,
62
+ Description = def . Description ,
63
+ NextExecution = 0 ,
64
+ CreateTime = DateTime . Now . ToUniversalTime ( ) ,
65
+ Status = WorkflowStatus . Runnable
66
+ } ;
67
+
68
+ if ( ( def . DataType != null ) && ( data == null ) )
69
+ {
70
+ wf . Data = TypeExtensions . GetConstructor ( def . DataType , new Type [ ] { } ) . Invoke ( null ) ;
71
+ }
72
+
73
+ wf . ExecutionPointers . Add ( new ExecutionPointer
74
+ {
75
+ Id = Guid . NewGuid ( ) . ToString ( ) ,
76
+ StepId = 0 ,
77
+ Active = true ,
78
+ StepName = Enumerable . First < WorkflowStep > ( def . Steps , x => x . Id == 0 ) . Name
79
+ } ) ;
80
+
81
+ string id = await _persistenceStore . CreateNewWorkflow ( wf ) ;
82
+ await _queueProvider . QueueWork ( id , QueueType . Workflow ) ;
83
+ return id ;
84
+ }
85
+
86
+ public async Task PublishEvent ( string eventName , string eventKey , object eventData , DateTime ? effectiveDate = null )
87
+ {
88
+ _logger . LogDebug ( "Creating event {0} {1}" , eventName , eventKey ) ;
89
+ Event evt = new Event ( ) ;
90
+
91
+ if ( effectiveDate . HasValue )
92
+ evt . EventTime = effectiveDate . Value . ToUniversalTime ( ) ;
93
+ else
94
+ evt . EventTime = DateTime . Now . ToUniversalTime ( ) ;
95
+
96
+ evt . EventData = eventData ;
97
+ evt . EventKey = eventKey ;
98
+ evt . EventName = eventName ;
99
+ evt . IsProcessed = false ;
100
+ string eventId = await _persistenceStore . CreateEvent ( evt ) ;
101
+
102
+ await _queueProvider . QueueWork ( eventId , QueueType . Event ) ;
103
+ }
104
+
105
+ public async Task < bool > SuspendWorkflow ( string workflowId )
106
+ {
107
+ if ( ! await _lockProvider . AcquireLock ( workflowId , new CancellationToken ( ) ) )
108
+ return false ;
109
+
110
+ try
111
+ {
112
+ var wf = await _persistenceStore . GetWorkflowInstance ( workflowId ) ;
113
+ if ( wf . Status == WorkflowStatus . Runnable )
114
+ {
115
+ wf . Status = WorkflowStatus . Suspended ;
116
+ await _persistenceStore . PersistWorkflow ( wf ) ;
117
+ return true ;
118
+ }
119
+
120
+ return false ;
121
+ }
122
+ finally
123
+ {
124
+ await _lockProvider . ReleaseLock ( workflowId ) ;
125
+ }
126
+ }
127
+
128
+ public async Task < bool > ResumeWorkflow ( string workflowId )
129
+ {
130
+ if ( ! await _lockProvider . AcquireLock ( workflowId , new CancellationToken ( ) ) )
131
+ {
132
+ return false ;
133
+ }
134
+
135
+ bool requeue = false ;
136
+ try
137
+ {
138
+ var wf = await _persistenceStore . GetWorkflowInstance ( workflowId ) ;
139
+ if ( wf . Status == WorkflowStatus . Suspended )
140
+ {
141
+ wf . Status = WorkflowStatus . Runnable ;
142
+ await _persistenceStore . PersistWorkflow ( wf ) ;
143
+ requeue = true ;
144
+ return true ;
145
+ }
146
+
147
+ return false ;
148
+ }
149
+ finally
150
+ {
151
+ await _lockProvider . ReleaseLock ( workflowId ) ;
152
+ if ( requeue )
153
+ await _queueProvider . QueueWork ( workflowId , QueueType . Workflow ) ;
154
+ }
155
+
156
+ return false ;
157
+ }
158
+
159
+ public async Task < bool > TerminateWorkflow ( string workflowId )
160
+ {
161
+ if ( ! await _lockProvider . AcquireLock ( workflowId , new CancellationToken ( ) ) )
162
+ {
163
+ return false ;
164
+ }
165
+
166
+ try
167
+ {
168
+ var wf = await _persistenceStore . GetWorkflowInstance ( workflowId ) ;
169
+ wf . Status = WorkflowStatus . Terminated ;
170
+ await _persistenceStore . PersistWorkflow ( wf ) ;
171
+ return true ;
172
+ }
173
+ finally
174
+ {
175
+ await _lockProvider . ReleaseLock ( workflowId ) ;
176
+ }
177
+ }
178
+
179
+ public void RegisterWorkflow < TWorkflow > ( )
180
+ where TWorkflow : IWorkflow , new ( )
181
+ {
182
+ TWorkflow wf = new TWorkflow ( ) ;
183
+ _registry . RegisterWorkflow ( wf ) ;
184
+ }
185
+
186
+ public void RegisterWorkflow < TWorkflow , TData > ( )
187
+ where TWorkflow : IWorkflow < TData > , new ( )
188
+ where TData : new ( )
189
+ {
190
+ TWorkflow wf = new TWorkflow ( ) ;
191
+ _registry . RegisterWorkflow < TData > ( wf ) ;
192
+ }
193
+ }
194
+ }
0 commit comments