Designing a Flexible Workflow Engine: From Simple Chains to Complex Nested Nodes
This article chronicles the step‑by‑step evolution of a workflow engine, detailing how simple sequential approvers were expanded into hierarchical trees supporting parallel, multi‑sign, conditional, proxy, and scripted nodes, while introducing state management, rejection handling, and progress metrics.
Level 1
The initial version implements a linear chain of approvers where each node records the current approver, moves to the next after approval, and ends when the final node is reached.
Level 2
Support for multi‑sign nodes is added; a multi‑sign node contains many approvers and only completes when all have approved. The design shifts from a simple linked list to a tree where leaf nodes are simple approvers and internal nodes represent complex structures.
Node states such as Ready, Complete, Future, and Waiting are introduced to control the flow.
Level 3
A parallel node is introduced; it is a complex node where any child node’s approval completes the whole node. A new state Skip is defined to deactivate sibling branches once one branch finishes.
Level 4
The tree structure is made fully recursive, allowing unlimited nesting of any node type, which enables arbitrarily complex workflows.
Level 5
Conditional nodes are added; they behave like parallel nodes but only activate child branches whose conditions evaluate to true based on form data.
Level 6
Simple nodes are classified into three approver types: fixed, derived from form fields, and computed via a mapping function (e.g., get_manager("Qian") ).
Level 7
Rejection to the initiator is implemented; only nodes in Ready state can reject, effectively restarting the workflow.
Level 8
Rejection to the previous approver is added, handling the complexity of nested nodes to locate the correct prior approver.
Level 9
Arbitrary‑node rejection is achieved by repeatedly rolling back until a Ready node matching the target is found.
Level 10
Time‑limit enforcement is added; nodes that exceed their allotted time are marked as timed‑out.
Level 11
Proxy (delegation) functionality is introduced by creating a parallel parent node and a sibling node for the proxy approver, allowing unlimited nesting of proxies.
Level 12
Cancellation of a proxy is implemented as the inverse operation, prohibited if the proxy has already approved.
Level 13
Pre‑ and post‑conditions are added to each node, requiring certain criteria before entry and before completion, significantly increasing code complexity.
Level 14
A progress metric is calculated as the distance from the leftmost node to the rightmost Ready node divided by the total distance, providing a percentage of workflow completion.
Level 15
Each node can now attach two executable scripts: one that runs when the node starts processing and another when it finishes.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.