Skip to content

Instantly share code, notes, and snippets.

Justin Heyes-Jones justinhj

Block or report user

Report or block justinhj

Hide content and notifications from this user.

Learn more about blocking users

Contact Support about this user’s behavior.

Learn more about reporting abuse

Report abuse
View GitHub Profile
View mbank9.scala
val finalState2 = finalEvents.map(eventToState).combineAll
println(show"Final state 2:\n$finalState2")
/* Output:
Final state 2:
Account holder: Ben Johnson
Balance: 80
*/
View mbank8.scala
val (finalEntity, finalEvents) =
commands.foldLeft((sampleAccount, List.empty[BankAccountEvent])) {
case ((acc, events), cmd) =>
val newEvents = acc.processCommand(cmd)
val newAcc = newEvents.foldLeft(acc) {
case (acc, evt) =>
acc.processEvent(evt)
}
(newAcc, events ++ newEvents)
}
View mbank7.scala
val t1 = Instant.now
val sampleAccount = AccountEntity(1, AccountState(0, None))
val commands = List(
DepositCmd(t1.plusSeconds(10), 100),
PurchaseCmd(t1.plusSeconds(20), 120),
AssignAccountHolderCmd(t1.plusSeconds(40), "Bob Johnson"),
DepositCmd(t1.plusSeconds(40), 100),
AssignAccountHolderCmd(t1.plusSeconds(50), "Ben Johnson"),
View mbank11.scala
case class AccountEntity(id: Int, state: AccountState)
extends PersistentEntity[Int, AccountEntity] {
override type Command = BankAccountCommand
override type Event = BankAccountEvent
override type State = AccountState
// Applies the command to the current state, returning a list of events
def processCommand(command: Command) : List[Event] = {
command match {
View mbank6.scala
def eventToState(event: BankAccountEvent): AccountState = {
event match {
case DepositEvt(time, amount) =>
AccountState(amount, None)
case PurchaseEvt(time, amount) =>
AccountState(-amount, None)
case AssignAccountHolderEvt(time, accountHolder) =>
AccountState(0, accountHolder.some)
}
}
View mbank5.scala
// When the left and right hand side are set we take the right side
(LastOption("Nero".some) |+| LastOption("Titus".some)).show
// res1: String = "Titus"
// When the left is None and the right hand side is set we also take the right side
(LastOption(None: Option[String]) |+| LastOption("Titus".some)).show
// res2: String = "Titus"
// When the left side is set and the right side is None we keep the left side
(LastOption("Nero".some) |+| LastOption(None: Option[String])).show
View mbank4.scala
AccountState(100, "Nero".some) |+| AccountState(120, "Titus".some)
// res1: AccountState = AccountState(220, Some("NeroTitus"))
View mbank3.scala
case class AccountState(balance: Int, accountHolder: LastOption[String])
object AccountState {
implicit def accountStateShow[A] = new Show[AccountState] {
def show(a: AccountState): String = {
show"Balance: ${a.balance}\nAccount holder: ${a.accountHolder}"
}
}
implicit val accountMonoid = new Monoid[AccountState] {
View mbank2.scala
sealed trait BankAccountCommand
case class DepositCmd(time: Instant, amount: Int) extends BankAccountCommand
case class PurchaseCmd(time: Instant, amount: Int) extends BankAccountCommand
case class AssignAccountHolderCmd(time: Instant, accountHolder: String) extends BankAccountCommand
sealed trait BankAccountEvent
case class DepositEvt(time: Instant, amount: Int) extends BankAccountEvent
case class PurchaseEvt(time: Instant, amount: Int) extends BankAccountEvent
case class AssignAccountHolderEvt(time: Instant, accountHolder: String) extends BankAccountEvent
View mbank1.scala
trait PersistentEntity[IDType, T <: PersistentEntity[IDType, T]] {
type Command
type Event
type State
def id: IDType
def state : State
def processCommand(command: Command) : List[Event]
def processEvent(event: Event) : T
You can’t perform that action at this time.