Building & Driving a Machine

Building a machine

Hydra.create(…​) takes a builder lambda. Inside it:

Builder call Purpose

mb.initialState(s)

The state the machine starts in (required).

mb.state(value, Class, sb → …)

Declare a state matched by value equality.

mb.state(Class, sb → …)

Declare a state matched by type.

mb.onTransition(listener)

A machine-wide listener fired on every transition.

Inside a state builder (sb):

Builder call Purpose

sb.on(event, Class, (state, event) → …)

A transition triggered by an event matched by value.

sb.on(Class, (state, event) → …)

A transition triggered by an event matched by type.

sb.transitionTo(state[, action])

Move to state, optionally carrying an action payload.

sb.dontTransition([action])

Stay in the current state (a self-loop), optionally emitting an action.

sb.onEnter(listener) / sb.onExit(listener)

Fire side effects when the state is entered / exited.

Driving a machine

Method Behaviour

transition(event)

Match-and-move. Mutates the current state (thread-safe), fires listeners, returns the Transition.

readTransitionAndNotifyListeners(fromState, event)

Computes the move and fires listeners without mutating in-memory state — derives the class from the instance (a 3-arg (fromStateClass, fromState, event) overload also exists). See Async Orchestrators.

getState() / state

The current state.

cloneWith { mb → … }

A new machine derived from this one (e.g. a different initial state); the original is untouched.

Thread safety

The current state lives in a single AtomicReference, and each transition does a synchronized match-and-move. Safe to drive from many concurrent worker threads; the state never tears.

// Push an event. The machine moves AND tells you what to do next.
var checkout = orderMachine.transition(new Checkout(4999, "1 Market St"));
orderMachine.getState();   // Placed[amountCents=4999, address=1 Market St]

Each valid push moves the state and hands you an action to carry out. An illegal push is rejected; the state is left untouched and there is no action to run — the outcome is one of three sealed Transition cases.