Finite State Machine · JVM
Your workflow is a subway map.
Hydra only takes the legal rides.
A tiny, thread-safe, type-safe library with a fluent DSL for finite state machines on the JVM — usable from Java and Kotlin. Declare the states your system can be in and the events that move between them. Hydra makes only the legal moves, models every outcome as a type, and emits an action on each transition — built for the hard case: driving long-running asynchronous orchestrators.
- 01 Placed Checkout ChargeCard
- 02 Shipped PaymentSucceeded ShipParcel
- 03 Cancelled PaymentFailed no action
- 04 Cancelled Cancel RefundCard
// why a state machine
Stations, turnstiles, one ride at a time.
Stations are states; the turnstiles between them are events — you
can't teleport between any two stations, only take the connections the map allows. Modelling a
workflow this way, instead of a tangle of if/else and callbacks, buys three
things that matter at scale.
-
01
Legal moves are explicit
Illegal transitions are rejected by construction, not discovered at runtime. The map is the contract.
-
02
Failures are types
Every push returns a sealed
Transition—Valid,Invalid, orNoFromState. The caller is forced to handle "this can't happen". -
03
Durable resume
Because the position is an explicit value, a run that dies mid-flight knows exactly which step it was at — and resumes from there.
// the order machine, as a line map
Read the whole machine at a glance.
Each track is one transition. Its colour is the station it leads to; the label reads Event (the input you push in) over Action (the command emitted out). A dashed track emits no action.
State
Where the machine is — a discrete station, held one at a time. May carry context: Placed(amount, address).
Event
Something that happened to the machine. You push it in — often a bare signal: PaymentSucceeded.
Action
A command the machine emits on a transition. You receive it and do the work: ShipParcel(address).
// two ways to drive the line
In-memory, or as a pure routing function.
A plain transition(event) is perfect for a synchronous, single-process machine. But Hydra
was built for the harder case — where the durable truth lives outside the JVM.
transition(event)
Match-and-move. Mutates the current state (thread-safe via a single AtomicReference), fires listeners, and hands you the Transition.
readTransitionAndNotifyListeners(…)
Answers "given I finished step X with exit event E, what runs next?" and fires listeners — without mutating in-memory state. Your store holds the real position.
Drive an orchestrator →One ride at a time. Only the legal ones.
Declare your states and events; let the compiler keep them straight.
Hydra.create(mb -> …)