StateReducer

fun interface StateReducer<S, P>

User-supplied fold function for reconstructing saga state from a journal.

During resume, the executor calls reduce once per journal entry in ascending ca.acendas.kstate.saga.journal.JournalEntry.seq order, starting with the saga's initialState. The accumulator returned by each call becomes the state argument for the next call.

Contract

  • Pure — must not perform I/O or mutate external state.

  • Deterministic — the same sequence of entries must always produce the same state.

  • Total — must handle every ca.acendas.kstate.saga.journal.EntryPhase; typically implementations early-return for phases they don't care about:

StateReducer<OrderState, OrderEvent> { state, entry ->
if (entry.phase != EntryPhase.Effect) return@StateReducer state
state.apply(entry.payload)
}
  • Exception-safe — if the reducer throws, the executor catches it and returns ResumeOutcome.CorruptJournal with reason = "reducer threw: <message>" and atSeq = entry.seq.

Example

data class PaymentState(val capturedAmount: Long = 0L)

val reducer = StateReducer<PaymentState, String> { state, entry ->
when {
entry.phase == EntryPhase.Effect && entry.step?.stringValue == "charge" ->
state.copy(capturedAmount = entry.payload.toLong())
else -> state
}
}

Parameters

S

The saga state type.

P

The journal payload type.

Functions

Link copied to clipboard
abstract fun reduce(state: S, entry: JournalEntry<P>): S

Folds entry into state, returning the updated state.