12. Behavior
final case class EventsourcedBehavior[F[_], Op[_], State, Event](
handler: Op ~> Handler[F, State, Event, ?],
zero: State,
reducer: (State, Event) => Folded[State]
)
Aecor ⇒ Purely functional event sourcing by @notxcain 12
13. State
zero: S
reducer: (S, E) => Folded[E]
sealed abstract class Folded[+A] extends Product with Serializable
final case object Impossible extends Folded[Nothing]
final case class Next[+A](a: A) extends Folded[A]
Aecor ⇒ Purely functional event sourcing by @notxcain 13
15. Operations
trait RepliesWith[A]
sealed abstract class AccountOp[A] extends Product with Serializable {
def accountId: AccountId
}
final case class OpenAccount(accountId: AccountId)
extends AccountOp[Either[OpenAccountRejection, Unit]]
final case class CreditAccount(accountId: AccountId, transactionId: AccountTransactionId, amount: Amount)
extends AccountOp[Either[CreditAccountRejection, Unit]]
final case class DebitAccount(accountId: AccountId, transactionId: AccountTransactionId, amount: Amount)
extends AccountOp[Either[DebitAccountRejection, Unit]]
Aecor ⇒ Purely functional event sourcing by @notxcain 15
17. Operation handler
type Handler[F[_], S, E, A] =
S => F[(Seq[E], A)]
type VanillaHandler[F[_], S, A] =
S => F[(S, A)]
Aecor ⇒ Purely functional event sourcing by @notxcain 17
18. Operation handler
type Handler[F[_], S, E, A] =
S => F[(Seq[E], A)]
type OperationHandler[F[_], Op[_], S, E] =
Op ~> Handler[F, S, E, ?]
Aecor ⇒ Purely functional event sourcing by @notxcain 18
19. Behavior
final case class EventsourcedBehavior[F[_], Op[_], State, Event](
handler: Op ~> Handler[F, State, Event, ?],
zero: State,
reducer: (State, Event) => Folded[State]
)
Aecor ⇒ Purely functional event sourcing by @notxcain 19
26. Process
Top 2
• Views
• Business-processes
Aecor ⇒ Purely functional event sourcing by @notxcain 26
27. Distributed Processing
final case class Process[F[_]](run: F[RunningProcess[F]])
Aecor ⇒ Purely functional event sourcing by @notxcain 27
28. Distributed Processing
final case class Process[F[_]](run: F[RunningProcess[F]])
final case class RunningProcess[F[_]](
watchTermination: F[Unit],
shutdown: () => Unit
)
Aecor ⇒ Purely functional event sourcing by @notxcain 28
29. Distributed Processing
def start[F[_]: Async: Capture: CaptureFuture: Functor](
name: String,
processes: Seq[Process[F]],
settings: DistributedProcessingSettings
): F[ProcessKillSwitch[F]] = ...
final case class ProcessKillSwitch[F[_]](shutdown: F[Unit])
Aecor ⇒ Purely functional event sourcing by @notxcain 29
30. Aecor - what else?
Experimental runtime for generic behaviors
final case class Behavior[F[_], Op[_]](run: Op ~> PairT[F, Behavior[F, Op], ?])
class GenericAkkaRuntime[F[_]: Async: CaptureFuture: Functor: Capture](system: ActorSystem) {
def start[Op[_]](entityName: String,
correlation: Correlation[Op],
behavior: Behavior[F, Op],
settings: GenericAkkaRuntimeSettings
): F[Op ~> F]
}
Aecor ⇒ Purely functional event sourcing by @notxcain 30
31. Aecor - what else?
Liberator (free algebra for trait, and many more)
@algebra
trait Account[F[_]] {
def openAccount(accountId: AccountId, owner: AccountOwner): F[Either[OpenAccountRejection, Unit]]
}
class EventSourcedAccount[F[_]](clock: F[ZonedDateTime])
extends Account[Handler[F, AccountState, AccountEvent, ?]]
val account: EventSourcedAggregate[Task] = ...
val handler: AccountOp ~> Handler[F, AccountState, AccountEvent, ?] = account.asFunctionK
Aecor ⇒ Purely functional event sourcing by @notxcain 31