Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package akka.persistence.typed.scaladsl
- import akka.actor.typed.Behavior
- import akka.persistence.typed.scaladsl.PersistentBehaviors.{CommandHandler, _}
- class AccountSpec {
- sealed trait AccountCommand
- case object CreateAccount extends AccountCommand
- case class Deposit(amount: Double) extends AccountCommand
- case class Withdraw(amount: Double) extends AccountCommand
- case object CloseAccount extends AccountCommand
- sealed trait AccountEvent
- case object AccountCreated extends AccountEvent
- case class Deposited(amount: Double) extends AccountEvent
- case class Withdrawn(amount: Double) extends AccountEvent
- case object AccountClosed extends AccountEvent
- sealed trait Account
- case class OpenedAccount(balance: Double) extends Account
- case object ClosedAccount extends Account
- private def initial: CommandHandler[AccountCommand, AccountEvent, Option[Account]] =
- (_, _, cmd) =>
- cmd match {
- case CreateAccount ⇒ Effect.persist(AccountCreated)
- }
- private def openedAccountHandlers(acc: OpenedAccount): CommandHandler[AccountCommand, AccountEvent, Option[Account]] =
- (ctx, _, cmd) => cmd match {
- case Deposit(amount) ⇒ Effect.persist(Deposited(amount))
- case Withdraw(amount) if (acc.balance - amount) < 0.0 =>
- throw new RuntimeException("Insufficient balance")
- case Withdraw(amount) =>
- Effect
- .persist(Withdrawn(amount))
- .andThen { st => // can't even use a PF here because this method is overloaded
- st match { // need to pattern match because state is Account, Effect is invariant on State
- case Some(OpenedAccount(balance)) =>
- // do some side-effect using balance
- println(balance)
- }
- }
- case CloseAccount if acc.balance == 0.0 =>
- Effect.persist(AccountClosed)
- case CloseAccount =>
- throw new RuntimeException("Account balance is not zero")
- }
- private def commandHandlers: CommandHandler[AccountCommand, AccountEvent, Option[Account]] =
- CommandHandler.byState {
- case None => CommandHandler.command {
- case CreateAccount => Effect.persist(AccountCreated)
- }
- case Some(acc@OpenedAccount(_)) => openedAccountHandlers(acc)
- case Some(ClosedAccount) => throw new RuntimeException("account already closed")
- }
- private def eventHandler(stateOpt: Option[Account], event: AccountEvent):Option[Account] =
- (stateOpt, event) match {
- case (None, AccountCreated) => Some(OpenedAccount(0.0))
- case (Some(acc@OpenedAccount(_)), Deposited(amount)) =>
- Some(acc.copy(balance = acc.balance + amount))
- case (Some(acc@OpenedAccount(_)), Withdrawn(amount)) =>
- Some(acc.copy(balance = acc.balance - amount))
- case (Some(acc@OpenedAccount(_)), AccountClosed) =>
- Some(ClosedAccount)
- // this or compiler warning. We should not need to do it
- case _ => throw new RuntimeException("this should never happen")
- }
- def behavior(accountNumber: String): Behavior[AccountCommand] =
- PersistentBehaviors.receive[AccountCommand, AccountEvent, Option[Account]](
- persistenceId = accountNumber,
- initialState = None,
- commandHandler = commandHandlers,
- eventHandler = eventHandler
- )
- }
Add Comment
Please, Sign In to add comment