A saga can be built using the SagaBuilder DSL.

This DSL is used to create saga actions, and define dependencies between them.

  1. Create a builder:
     import io.simplesource.saga.client.dsl.SagaDSL;
     import static io.simplesource.saga.client.dsl.SagaDSL;
        
     SagaBuilder<A> sagaBuilder = SagaDSL.createBuilder();
    
  2. 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);
     ...
    

    A is the serializable action command type, typically something like SpecificRecord.

  3. Create dependencies between them:

    Examples:

    Execute a, then b, then c:

     a.andThen(b).andThen(c)
    

    Execute a, then b, c and d in parallel, then e:

     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, then b, c and d in series, then e. 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 andThen operator 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.

  4. 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