A saga can be built using the SagaBuilder DSL.
This DSL is used to create saga actions, and define dependencies between them.
- Create a builder:
import io.simplesource.saga.client.dsl.SagaDSL; import static io.simplesource.saga.client.dsl.SagaDSL; SagaBuilder<A> sagaBuilder = SagaDSL.createBuilder(); - Define some actions:
SubSaga<A> a = sagaBuilder.addAction(actionIdA, actionCommandA, undoCommandA); SubSaga<A> b = sagaBuilder.addAction(actionIdB, actionCommandB, undoCommandB); SubSaga<A> c = sagaBuilder.addAction(actionIdC, actionCommandC, undoCommandC); ...Ais the serializable action command type, typically something likeSpecificRecord. -
Create dependencies between them:
Examples:
Execute
a, thenb, thenc:a.andThen(b).andThen(c)
Execute
a, thenb,canddin parallel, thene:a.andThen(b).andThen(e) a.andThen(c).andThen(e) a.andThen(d).andThen(e)This can also be expressed as:
a.andThen(inParallel(b, c, d)).andThen(e)
Execute
a, thenb,canddin series, thene. The following are equivalent:a.andThen(b).andThen(c).andThen(d).andThen(e) inSeries(a, b, c).andThen(d).andThen(e) inSeries(a, b, c, d, e) a.andThen(inSeries(b, c, d)).andThen(e) inSeries(List.of(a, b, c, d, e))The latter is useful when we have a sequence of actions of length only known at runtime.
The
andThenoperator is associative. This means that the following are equivalent:a.andThen(b).andThen(c)and
a.andThen(b.andThen(c))This associativity property enables building larger sagas from smaller ones.
- Build the saga:
Result<SagaError, Saga<A>> sagaBuildResult = sagaBuilder.build();If the Saga fails validation,such as has cyclical references or attempts to combine subsagas created with different builders, an error is created.
Scala DSL
A DSL is available for Scala users, loosely based on Akka Streams, equivalent to the Java DSL, but prettier and easier to read.
Examples:
a ~> b ~> c
a ~> inParallel(b, c, d) ~> e
a ~> List(b, c, d).inParallel ~> e