88import org .zstack .core .CoreGlobalProperty ;
99import org .zstack .core .Platform ;
1010import org .zstack .core .errorcode .ErrorFacade ;
11+ import org .zstack .header .core .AsyncBackup ;
1112import org .zstack .header .core .progress .ProgressFlowChainProcessorFactory ;
1213import org .zstack .header .core .workflow .*;
1314import org .zstack .header .errorcode .ErrorCode ;
2324import java .util .*;
2425import java .util .Map .Entry ;
2526import java .util .concurrent .ConcurrentHashMap ;
27+ import java .util .function .Consumer ;
2628import java .util .function .Function ;
2729
2830import static org .zstack .core .Platform .inerr ;
@@ -62,6 +64,7 @@ public class SimpleFlowChain implements FlowTrigger, FlowRollback, FlowChain, Fl
6264 private List <List <Runnable >> afterDone = new ArrayList <>();
6365 private List <List <Runnable >> afterError = new ArrayList <>();
6466 private List <List <Runnable >> afterFinal = new ArrayList <>();
67+ private List <AsyncBackup > asyncBackups = new ArrayList <>();
6568
6669 @ Autowired (required = false )
6770 ProgressFlowChainProcessorFactory progressFactory ;
@@ -131,11 +134,20 @@ public SimpleFlowChain() {
131134 id = "FCID_" + Platform .getUuid ().substring (0 , 8 );
132135 }
133136
137+ public SimpleFlowChain (String chainName ) {
138+ this ();
139+ this .name = chainName ;
140+ }
141+
134142 public SimpleFlowChain (Map <String , Object > data ) {
135143 id = "FCID_" + Platform .getUuid ().substring (0 , 8 );
136144 this .data .putAll (data );
137145 }
138146
147+ public static SimpleFlowChain of (String chainName ) {
148+ return new SimpleFlowChain (chainName );
149+ }
150+
139151 @ Override
140152 public List <Flow > getFlows () {
141153 return flows ;
@@ -228,6 +240,12 @@ public SimpleFlowChain then(Flow flow) {
228240 return this ;
229241 }
230242
243+ public SimpleFlowChain then (String flowName , Consumer <FlowTrigger > consumer ) {
244+ return then (Flow .of (flowName )
245+ .handle (consumer )
246+ .build ());
247+ }
248+
231249 public SimpleFlowChain ctxHandler (FlowContextHandler handler ) {
232250 DebugUtils .Assert (contextHandler ==null , "there has been an FlowContextHandler installed" );
233251 contextHandler = handler ;
@@ -240,6 +258,21 @@ public SimpleFlowChain error(FlowErrorHandler handler) {
240258 return this ;
241259 }
242260
261+ @ SuppressWarnings ("rawtypes" )
262+ public SimpleFlowChain error (Consumer <ErrorCode > handler ) {
263+ AsyncBackup firstAsyncBackup = this .asyncBackups .isEmpty () ? null : this .asyncBackups .get (0 );
264+ AsyncBackup [] otherAsyncBackups = this .asyncBackups .isEmpty () ? new AsyncBackup [0 ] :
265+ this .asyncBackups .subList (1 , this .asyncBackups .size ()).toArray (new AsyncBackup [0 ]);
266+
267+ DebugUtils .Assert (handler != null , "handler of errorHandler should not be null" );
268+ return error (new FlowErrorHandler (firstAsyncBackup , otherAsyncBackups ) {
269+ @ Override
270+ public void handle (ErrorCode errCode , Map data ) {
271+ handler .accept (errCode );
272+ }
273+ });
274+ }
275+
243276 @ Override
244277 public FlowChain Finally (FlowFinallyHandler handler ) {
245278 finallyHandler = handler ;
@@ -285,13 +318,39 @@ public Map getData() {
285318 return this .data ;
286319 }
287320
321+ public SimpleFlowChain propagateExceptionTo (AsyncBackup ... backups ) {
322+ DebugUtils .Assert (backups != null , "backups in methods propagateExceptionTo() must be not null" );
323+ DebugUtils .Assert (Arrays .stream (backups ).noneMatch (Objects ::isNull ),
324+ "backups in propagateExceptionTo() should not contain null elements" );
325+ DebugUtils .Assert (doneHandler == null , "propagateExceptionTo() must be called before SimpleFlowChain.done()" );
326+ DebugUtils .Assert (errorHandler == null , "propagateExceptionTo() must be called before SimpleFlowChain.error()" );
327+ DebugUtils .Assert (finallyHandler == null , "propagateExceptionTo() must be called before SimpleFlowChain.Finally()" );
328+ this .asyncBackups .addAll (Arrays .asList (backups ));
329+ return this ;
330+ }
331+
288332 @ Override
289333 public SimpleFlowChain done (FlowDoneHandler handler ) {
290334 DebugUtils .Assert (doneHandler ==null , "there has been a FlowDoneHandler installed" );
291335 doneHandler = handler ;
292336 return this ;
293337 }
294338
339+ @ SuppressWarnings ("rawtypes" )
340+ public SimpleFlowChain done (Runnable runnable ) {
341+ AsyncBackup firstAsyncBackup = this .asyncBackups .isEmpty () ? null : this .asyncBackups .get (0 );
342+ AsyncBackup [] otherAsyncBackups = this .asyncBackups .isEmpty () ? new AsyncBackup [0 ] :
343+ this .asyncBackups .subList (1 , this .asyncBackups .size ()).toArray (new AsyncBackup [0 ]);
344+
345+ DebugUtils .Assert (runnable != null , "runnable of doneHandler should not be null" );
346+ return done (new FlowDoneHandler (firstAsyncBackup , otherAsyncBackups ) {
347+ @ Override
348+ public void handle (Map data ) {
349+ runnable .run ();
350+ }
351+ });
352+ }
353+
295354 private void collectAfterRunnable (Flow flow ) {
296355 List <Field > ad = FieldUtils .getAnnotatedFieldsOnThisClass (AfterDone .class , flow .getClass ());
297356 for (Field f : ad ) {
0 commit comments