-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add deployer generic abstraction that captures sharded repository ope…
…ration
- Loading branch information
Jonas Chapuis
committed
Sep 13, 2023
1 parent
7727601
commit f004fb4
Showing
1 changed file
with
86 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package endless.core.entity | ||
|
||
import cats.effect.kernel.Resource | ||
import endless.core.entity.Deployer.{InterpretedEffector, InterpretedEntity, InterpretedRepository} | ||
import endless.core.event.EventApplier | ||
import endless.core.interpret.EffectorT.EffectorT | ||
import endless.core.interpret.EntityT | ||
import endless.core.protocol.CommandProtocol | ||
|
||
/** `Deployer` deploys entity repositories by assembling the required interpreters and components. | ||
*/ | ||
trait Deployer { | ||
|
||
/** Deploys an entity repository in context `F`, returning an instance of its algebra wrapped in a | ||
* resource (since deployments typically require finalization). | ||
* | ||
* Repository operation uses the three provided interpreters in combination, following a strictly | ||
* defined sequence: | ||
* - the interpreted repository is used to create a handle on the entity with the specified ID, | ||
* which implements the entity algebra. This allows further interaction with the entity by | ||
* the caller of the repository algebra. | ||
* - the interpreted entity runs invoked function on the entity algebra: this possibly involves | ||
* reading the entity state (e.g. for validation), and writing events (which affect the | ||
* state) | ||
* - after events were written, a possible side-effect is triggered: this can be asynchronous | ||
* (i.e. the function doesn't wait for completion) | ||
* - the function finally returns to the caller of entity algebra | ||
* | ||
* This interaction pattern occurs with "actor-like" semantics: all calls on the entity are | ||
* processed in sequence. | ||
* | ||
* @param repository | ||
* provides access to to an entity with a specific ID via its algebra | ||
* @param entity | ||
* runs calls on entity algebra | ||
* @param effector | ||
* handles side-effects after entity interaction | ||
* @param nameProvider | ||
* provides a name for the entity (in other words, the "type of entity", e.g. "booking") | ||
* @param commandProtocol | ||
* protocol-centric definition of entity algebra: defines a wire encoding for interactions with | ||
* remote entities | ||
* @param eventApplier | ||
* defines how events are applied to the entity state | ||
* @tparam ID | ||
* entity ID | ||
* @tparam S | ||
* entity state | ||
* @tparam Alg | ||
* entity algebra | ||
* @tparam RepositoryAlg | ||
* repository algebra | ||
* @tparam EffectorAlg | ||
* effector algebra | ||
* @return | ||
* a resource encapsulating access to the repository algebra | ||
*/ | ||
def deployRepository[F[_], ID, S, E, Alg[_[_]], RepositoryAlg[_], EffectorAlg[_]]( | ||
repository: InterpretedRepository[F, ID, Alg, RepositoryAlg], | ||
entity: InterpretedEntity[F, S, E, Alg], | ||
effector: InterpretedEffector[F, S, Alg, RepositoryAlg, EffectorAlg] | ||
)(implicit | ||
nameProvider: EntityNameProvider[ID], | ||
commandProtocol: CommandProtocol[Alg], | ||
eventApplier: EventApplier[S, E] | ||
): Resource[F, RepositoryAlg[F]] | ||
|
||
} | ||
|
||
object Deployer { | ||
trait InterpretedEntity[F[_], S, E, Alg[_[_]]] { | ||
def apply(entity: Entity[EntityT[F, S, E, *], S, E]): F[Alg[EntityT[F, S, E, *]]] | ||
} | ||
|
||
trait InterpretedRepository[F[_], ID, Alg[_[_]], RepositoryAlg[_]] { | ||
def apply(repository: Repository[F, ID, Alg]): F[RepositoryAlg[F]] | ||
} | ||
|
||
trait InterpretedEffector[F[_], S, Alg[_[_]], RepositoryAlg[_], EffectorAlg[_]] { | ||
def apply( | ||
effector: Effector[EffectorT[F, S, Alg, *], S, Alg], | ||
repositoryAlg: RepositoryAlg[F], | ||
entityAlg: Alg[F] | ||
): F[EffectorAlg[F]] | ||
} | ||
} |