Deployer
trait Deployer {
def deployRepository[F[_]: Async, ID: EntityIDCodec, S, E, Alg[_[_]], RepositoryAlg[_[_]]](
repository: RepositoryInterpreter[F, ID, Alg, RepositoryAlg],
behavior: BehaviorInterpreter[F, S, E, Alg],
sideEffect: SideEffectInterpreter[F, S, Alg, RepositoryAlg]
)(implicit
nameProvider: EntityNameProvider[ID],
commandProtocol: CommandProtocol[ID, Alg],
eventApplier: EventApplier[S, E],
parameters: DeploymentParameters[F, ID, S, E]
): Resource[F, Deployment[F, RepositoryAlg]]
}
Deployer
brings everything together to “materialize” an entity repository. It returns a Deployment
instance wrapped in a cats-effect Resource
(to support finalization). The Deployment
type is defined by implementers (aka. the runtime, e.g. PekkoDeployer
), and is meant to provide a RepositoryAlg
instance allowing for interactions with the deployed repository. It can also expose extra fields or methods that are relevant to the particular runtime.
deployRepository
is parametrized with the following type parameters:
F[_]
: abstract effectful contextF
encapsulating all values, e.g.IO[*]
Alg[_[_]]
: algebra allowing interaction with the entity, e.g. BookingAlg[IO[*]]RepositoryAlg[_[_]]
: repository algebra, e.g. BookingsAlg[IO[*]]ID
: entity ID, e.g.final case class BookingID(id: UUID) extends AnyVal
S
: entity state, e.g. BookingE
: entity event, e.g. BookingEvent
Repository operation is defined by the interpreted repository, behavior and side-effect algebras, following a strictly defined sequence:
- the interpreted repository is used to create a handle on the entity with the specified ID. This handle implements the entity algebra, using which the caller can interact with the entity.
- when a function of the entity algebra is invoked, the invocation is serialized using the
commandProtocol
and sent over the wire thanks to CommandSender. It is then decoded on the server side and run with the providedbehavior
interpreter: this typically involves reading the entity state (e.g. for validation) and writing events (which leads to a new version of the state via theeventApplier
folding function) - after events are written, a possible side-effect is triggered: this supports asynchronicity (i.e. starting fibers)
- the function finally returns to the caller with the result of the operation, encoded over the wire as a reply using
commandProtocol
and delivered back to the caller thanks toCommandSender
.
See also sequence diagrams in Example App that represent this flow for a concrete entity.
0.31.0