folio-flow-engine
- 1 Overview
- 2 Key Functionality
- 3 Interfaces and models
- 3.1 Flow / Flow Builder
- 3.2 Flow Engine
- 3.2.1 Builder
- 3.2.2 Stage Report Provider
- 3.3 Stage
- 3.3.1 Flow Methods
- 3.3.2 Listenable Methods
- 3.4 Parallel Stage
- 3.4.1 Parallel Stage Builder
- 3.5 Dynamic Stage
- 3.6 Stage Context
- 3.7 Stage executor
- 4 Logging
Overview
folio-flow-engine is a Java library, that utilizes native classes for Asynchronous execution like CompletableFuture, ExecutorService etc. to provide a friendly interface for composing tasks to be executed with different rules.
GitHub repository:
GitHub - folio-org/folio-flow-engine
Key Functionality
Flow engine provides the following functionality:
Asynchronous execution
Stage execution in sequence
Stage execution in parallel
Complex flow execution, including execution of nested flows in parallel
Dynamic stage generation based on context data
Stage cancellation of one of the upstream stages failed
Stage execution observability
methods to observe critical moments of stage execution
explicit logging, including flow engine reports in logs
Java-friendly context management using the Decorator pattern
Sequence Task Execution
Description
The Flow Engine allows tasks to be executed in a specific order, ensuring each task is completed before the next one begins.
Usage
Define a sequence of tasks in the desired order.
The Flow Engine will execute each task one after the other.
If a task fails, subsequent tasks in the sequence will not be executed.
Flow engine follows the following scenarios:
Simple flow execution
A flow engine can execute stages in sequence, waiting for the previous stage to be finished before executing the next one.
Data can be transferred between stages using StageContext model.
Stage context store data with key as String and value as Object. There is a way to make context more Java-friendly using AbstractStageContextWrapper
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(task2)
.stage(task3)
.build();Simple flow execution (failed stage)
When one of the stages in flow fails - the flow manager stops the execution and calls onFlowErrorStage (if defined)
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(task2)
.stage(task3)
.stage(task4)
.onFlowError(onFlowErrorStage)
.build();This behavior is default, and it can be re-configured:
Flow.builder()
// stages
.executionStrategy(CANCEL_ON_ERROR | IGNORE_ON_ERROR)
.build()Simple flow execution (failed stage with cancellation)
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(task2)
.stage(task3)
.stage(task4)
.onFlowCancellation(onFlowCancellationStage)/ta
.executionStrategy(CANCEL_ON_ERROR)
.build();Parallel Task Execution
Description
The Flow Engine supports the execution of multiple tasks simultaneously, leveraging concurrency to improve efficiency and reduce total execution time.
Usage
Define tasks that can be executed in parallel.
The Flow Engine will manage the concurrent execution of these tasks.
parallelism is configured in the
FlowEnginecomponent
If one task fails, all parallel tasks will be canceled except failed ones (if the strategy is
CANCEL_ON_ERROR).
Parallel Stage execution
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(ParallelStage.of(task2_1, task2_2, task2_3))
.stage(task3)
.build();Note that parallelism is customizable by defining an executor when building FlowEngine component
public FlowEngine flowEngine() {
return FlowEngine.builder()
.name("flow-engine")
.executor(/* custom executor can be defined here */))
.executionTimeout(/* stage timeout execution can be defined here */)
.build();
}Parallel Stage execution(stage failed)
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(ParallelStage.of(task2_1, task2_2, task2_3))
.stage(task3)
.onFlowError(onFlowErrorStage)
.build();Parallel Stage execution (stage failed with cancellation)
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(ParallelStage.of(task2_1, task2_2, task2_3))
.stage(task3)
.onFlowCancellation(onFlowCancellationStage)
.executionStrategy(CANCEL_ON_ERROR)
.build();Nested flow execution
var flow1 = Flow.builder()
.id("Flow 1")
.stage(task2_1_1)
.stage(task2_1_2)
.build();
var flow2 = Flow.builder()
.id("Flow 1")
.stage(task2_2_1)
.stage(task2_2_2)
.build();
Flow.builder()
.id("Simple Flow")
.stage(task1)
.stage(ParallelStage.of(flow1, flow2))
.stage(task3)
.build();Interfaces and models
Flow / Flow Builder
Provides a Flow object, containing a sequence of stages and flows to be executed
Sucessfull flow executions are always finished without exceptions
If error is occurred during flow execution and
executionStrategyisIGNORE_ON_ERROR- thenFlowExecutionExceptionwill be raised with a reason in causeIf error is occurred during flow execution and
executionStrategyisCANCEL_ON_ERROR- thenFlowCancelledExceptionwill be raised with a reason of cancellation in causeFlowCancellationExceptionwill be raised with a reason of cancellation failure in cause