Checkpointing and Recovery
Elements described below are used primarily for evolving workflows, see the dedicated docs for details.
The elements below are technical in nature and behave differently during rendering.
BpmnRenderer
will not render them at all, while MermaidRenderer
will render them only with showTechnical=true
.
Checkpointing
Checkpointing allows you to emit a state-capturing event that, during recovery, marks the wrapped part of the workflow as complete. This is particularly useful for:
- Skipping the full recovery of previously completed workflow segments
- Enabling workflow evolution by allowing parts of the workflow to be modified or removed
When a workflow is executed, the saveState
function is called to generate an event that captures the current state.
During recovery, the recoverState
function is used to rebuild the state from the event,
allowing the workflow to override recovery of the wrapped logic.
val myWorkflow: WIO[Int, Nothing, MyState] = WIO.pure(MyState(1)).autoNamed
def saveState(input: Int, state: MyState): MyEvent = ???
def recoverState(input: Int, event: MyEvent): MyState = ???
val checkpointed = myWorkflow.checkpointed(saveState, recoverState)
Rendering Outputs
- Flowchart
- Model
{
"base" : {
"meta" : {
"name" : "My Workflow",
"error" : null
},
"_type" : "Pure"
},
"_type" : "Checkpoint"
}
Error Handling
If an error is emitted from within a checkpointed workflow segment, the checkpointing is ignored, and the error is propagated normally. This ensures that checkpointing doesn't interfere with the error handling mechanisms of the workflow.
Recovery
Recovery allows processing an event that has been previously emitted. The event must be inserted into the journal outside the current workflow, either by previous checkpointing or manual operations.
This method creates a workflow that doesn't execute any logic but instead directly processes an event to recover a state. It's particularly useful when:
- Migrating workflows to a new version where parts of the original workflow have been removed
- Integrating with external changes that generate events outside the workflow
def recoverState(input: Int, event: MyEvent): MyState = ???
val myWorkflow: WIO[Int, Nothing, MyState] = WIO.recover(recoverState)
Rendering Outputs
- Flowchart
- Model
{
"_type" : "Recovery"
}
Practical Usage
In practice, checkpointing and recovery are often used together to enable workflow evolution. For example:
- Version 1 of a workflow includes a segment that is checkpointed
- Version 2 of the workflow removes that segment but includes a recovery mechanism
- When a workflow instance created with version 1 is resumed using version 2, the recovery mechanism processes the checkpoint event, allowing the workflow to continue without the removed segment