Side-effect

trait SideEffect[F[_], S, Alg[_[_]]] {
  def apply(trigger: SideEffect.Trigger, effector: Effector[F, S, Alg]): F[Unit]

  def runModeFor(trigger: SideEffect.Trigger, state: Option[S]): F[SideEffect.RunMode] 
}

SideEffect is parametrized with the following type parameters:

  • F[_]: abstract effectful context F encapsulating all values, e.g. IO[*]
  • Alg[_[_]]: entity algebra, allowing “back-interaction” with the entity itself (e.g. for at least once process definition, see note in Effector)
  • S: entity state, e.g. Booking

It represents a side-effect that is triggered according to trigger either after event persistence, command handling (for a read-only behavior invocation) or recovery. Side-effects are typically asynchronous operations such as kafka writes, outgoing REST requests, and entity passivation (flushing out of memory).

In the runtime, the resulting F[Unit] is interpreted according to the RunMode setting indicated by a preliminary call to runModeFor. With Async mode, it triggers in run & forget mode so that command reply is not delayed by any lengthy side-effect. With Async mode, it triggers in run & forget mode so that any lengthy side-effect does not delay command reply. With Sync mode, the side-effect runs to completion before the entity processes the next command: this can simplify the side-effect logic as it precludes accounting for concurrency, but can hurt the system’s responsiveness. The default implementation of runModeFor sets it to Async.

The passed Effector instance can be used to access entity state, chain further interactions with the entity itself and to control passivation (for an example, see BookingEffector

Note

Defining a side-effect is entirely optional, pass-in SideEffectInterpreter.unit in deployRepository if there are no side-effects to describe.