A low-footprint Workflow Execution Framework to build and execute configured DAGs.
The highlights of this framework is its ability to configure within code, with the support for Data and Control Dependencies along with packaging logical blocks as Capabilities.
An arbitrary piece of logic wrapped in the execute
method. There are different flavours of bizlogics to cater to
custom needs - like Data Adapters, Enrichers and Validators.
A bizlogic that lets the execute
method return an immutable value object.
A bizlogic that can be used to validate arbitrary items and set a status on them.
A bizlogic that lets the execute
method return a mutable object, whose value can be enriched
over the course of the
flow.
A capability is a collection of bizlogics. It defines a logical feature in any large arbitrary system. Such a system is
made up of 1 more pluggable
capabilities.
A Flow represents a set of bizlogic to be executed in a strict pre-defined order (topologically sorted) to adhere to the defined dependencies.
Tef has a FluentCapabilityBuilder
which exposes a fluent api to build a flow. It supports apis to
- Add bizlogics and its various flavors to the flow.
- Define control dependencies between bizlogics.
- Add capabilities to a flow.
- Exclude arbitrary bizlogics from a flow.
- Add implicit bindings (more on this later in the doc)
The FlowBuilder
takes all the input from FluentCapabilityBuilder
and topologically sorts the bizlogics, returning a
flat list of bizlogics to be executed. Flow Builder ensures the generated flow is a DAG. If cycles are found in the
definition, flow build fails at runtime.
Tef supports 2 types of dependency - Control Dependency and Data Dependency
Here a Bizlogic A
is said to depend upon another Bizlogic B
, in which case Tef ensures B
will get executed
before A
.
Here a Bizlogic A
is said to depend upon Data B
.
Bizlogic A
does not know how the Data B's
value is computed. Tef ensures that the data adapter responsible for
emitting Data B
is executed before Bizlogic A
.
A data dependency can either be satisfied by another Data Adapter, or if the data is provided upfront at the start of the flow execution. This is known as an Implicit Binding.
Tef has a FluentFlowBuilder
There are various flags that can be passed to a data injection viz. mutable
, nullable
, name
and optional
.
If a DataAdapter is injecting dependent data, and if that data can change, the injection can be marked as mutable. In such cases, when the injected data changes, the injectee data adapter will get re-triggered.
This flag should be used on the bizlogics which are ok to receive a null value for this injection.
Name of the Injected data for specificity
This parameter is indicative of the fact that the particular injection is optional. No checks will be performed if there are no data adapters present for this injection. Such injections will only be served via the ImplicitBindings.
MutationListener
provides an ability to plug a callback when data returned a DataAdapter changes.
FlowExecutionListener
provides an ability to listen to lifecycle hooks in during flow execution
Refer to tests for detailed use-cases.
@bageshwar