This file contains hidden or 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
"handle deposit and successful withdrawal" in withTestDriver | |
{ driver => | |
val t1 = Instant.now | |
val t2 = t1.plusSeconds(100) | |
val outcome = driver.run(DepositCmd(t1, "Opening deposit", 100)) | |
outcome.replies should contain only 100 | |
val outcome2 = driver.run(WithdrawCmd(t2, "Transfer to savings", 20)) | |
outcome2.replies should contain only SuccessfulWithdrawalResponse(80) |
This file contains hidden or 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
.onEvent { | |
case (WithdrawEvt(time, description, amount), state) => | |
AccountState(state.balance - amount) | |
case (DepositEvt(time, description, amount), state) => | |
AccountState(state.balance + amount) | |
case (AssignAccountHolderEvt(time, accountHolder), state) => | |
Account(state.balance, Some(accountHolder)) | |
} |
This file contains hidden or 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
.onCommand[WithdrawCmd, WithdrawalResponse]{ | |
case (WithdrawCmd(time, description, amount), ctx, state) => | |
if(state.balance - amount >= 0) | |
ctx.thenPersist(WithdrawEvt(time, description, amount)){ _ => | |
ctx.reply(SuccessfulWithdrawalResponse(state.balance - amount)) | |
} | |
else { | |
ctx.reply(FailedWithdrawalResponse(s"Insufficient funds (current balance ${state.balance})")) | |
ctx.done | |
} |
This file contains hidden or 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
override def behavior = { | |
Actions().onCommand[DepositCmd, Int]{ | |
case (DepositCmd(time, description, amount), ctx, state) => | |
ctx.thenPersist(DepositEvt(time, description, amount)){ _ => | |
ctx.reply(state.balance + amount) | |
} | |
// ... |
This file contains hidden or 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
sealed trait BankAccountCommand[R] extends ReplyType[R] | |
case class DepositCmd(time: Instant, description: String, amount: Int) | |
extends BankAccountCommand[Int] | |
case class WithdrawCmd(time: Instant, description: String, amount: Int) | |
extends BankAccountCommand[WithdrawalResponse] | |
case class AssignAccountHolderEvt(time: Instant, accountHolder: String) | |
extends BankAccountEvent |
This file contains hidden or 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
case class Account(balance: Int, accountHolder: Option[String]) | |
class BankAccountEntity extends PersistentEntity { | |
override type Command = BankAccountCommand[_] | |
override type Event = BankAccountEvent | |
override type State = AccountState | |
override def initialState : State = Account(0, None) | |
def behavior = ??? // To come later |
This file contains hidden or 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
// Create a custom threadpool and execution context for Akka to use | |
val executor: ExecutorService = Executors.newFixedThreadPool(4, new ThreadFactory() { | |
override def newThread(r: Runnable): Thread = { | |
val t = Executors.defaultThreadFactory.newThread(r) | |
t.setDaemon(true) | |
t | |
} | |
}) |
This file contains hidden or 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
// Ammonite repl output | |
@ desugar { | |
for ( | |
s <- List(1,2,3); | |
o <- if(s % 2 == 1) Some(s) else None | |
) yield (s + o) | |
} | |
res12: Desugared = scala.collection.immutable.List.apply[Int](1, 2, 3).flatMap[Int, Any](((s: Int) => scala.Option.option2Iterable[Int]((if (s.%(2).==(1)) | |
scala.Some.apply[Int](s) |
This file contains hidden or 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
import cats._ | |
import cats.data._ | |
import cats.implicits._ | |
object EitherTLogging { | |
def divide[F[_]](dividend: Int, divisor: Int)(implicit F: ApplicativeError[F, String]): F[Int] = { | |
if (divisor === 0) F.raiseError("division by zero") | |
else F.pure(dividend / divisor) | |
} |
This file contains hidden or 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
import cats._ | |
import cats.instances._ | |
import cats.syntax._ | |
import cats.data.Validated._ | |
type ErrorOr[A] = Validated[String, A] | |
def logDivide(a: Int, b: Int) = WriterT[ErrorOr, String, Int]( | |
divide[ErrorOr](a,b) match { | |
case Invalid(e) => Invalid("Division by zero\n") |