为什么这个 akka FSM actor 中的数据总是空的?
Why is data always empty in this akka FSM actor?
代码如下:
package com.packt.akka
import akka.actor.{ActorSystem, FSM, Props, Stash}
object UserStorageFSM {
// FSM State
sealed trait State
case object Connected extends State
case object Disconnected extends State
// FSM Data
sealed trait Data {
def data: List[User]
}
case object EmptyData extends Data {
val data = List.empty
}
trait DBOperation
object DBOperation {
case object Create extends DBOperation
case object Update extends DBOperation
case object Read extends DBOperation
case object Delete extends DBOperation
}
case object Connect
case object Disconnect
case class Operation(op: DBOperation, user: User)
case class User(username: String, email: String)
}
class UserStorageFSM extends FSM[UserStorageFSM.State, UserStorageFSM.Data] with Stash {
import UserStorageFSM._
// 1. define start with
startWith(Disconnected, EmptyData)
// 2. define states
when(Disconnected) {
case Event(Connect, _) =>
println("UserStorage Connected to DB")
unstashAll()
goto(Connected) using (EmptyData)
case Event(_, _) =>
stash()
stay using (EmptyData)
}
when(Connected) {
case Event(Disconnect, _) =>
println("UserStorage disconnected from DB")
goto(Disconnected) using EmptyData
case Event(Operation(op, user), oldData) =>
op match {
case DBOperation.Create =>
stay using new Data {
override def data = user :: oldData.data
}
case DBOperation.Delete => stay using new Data {
override def data = oldData.data.filter(_ != user)
}
case DBOperation.Read => {
println(oldData.data)
stay using oldData
}
case DBOperation.Update => {
stay using new Data {
override def data: List[User] = user :: oldData.data.filter(_.username != user.username)
}
}
}
stay using EmptyData
}
// 3. initialize
initialize()
}
object FiniteStateMachine extends App {
import UserStorageFSM._
val system = ActorSystem("Hotswap-FSM")
val userStorage = system.actorOf(Props[UserStorageFSM], "userStorage-fsm")
userStorage ! Connect
userStorage ! Operation(DBOperation.Create, User("Admin", "admin@packt.com"))
userStorage ! Operation(DBOperation.Create, User("Admin1", "admin@packt.com"))
userStorage ! Operation(DBOperation.Read, User("Admin", "admin@packt.com"))
userStorage ! Disconnect
Thread.sleep(1000)
system.terminate()
}
模拟一个允许CRUD操作的存储系统。这里的问题是系统似乎总是包含空数据。这里出了什么问题?
在 Operation
的处理程序中,您在 op
的模式匹配中调用 stay
,但随后在底部调用 stay using EmptyData
,这就是那个习惯了。从 case Event(Operation(op, user), oldData) =>
的底部删除 stay using EmptyData
,您应该会开始看到更新后的 Data
.
代码如下:
package com.packt.akka
import akka.actor.{ActorSystem, FSM, Props, Stash}
object UserStorageFSM {
// FSM State
sealed trait State
case object Connected extends State
case object Disconnected extends State
// FSM Data
sealed trait Data {
def data: List[User]
}
case object EmptyData extends Data {
val data = List.empty
}
trait DBOperation
object DBOperation {
case object Create extends DBOperation
case object Update extends DBOperation
case object Read extends DBOperation
case object Delete extends DBOperation
}
case object Connect
case object Disconnect
case class Operation(op: DBOperation, user: User)
case class User(username: String, email: String)
}
class UserStorageFSM extends FSM[UserStorageFSM.State, UserStorageFSM.Data] with Stash {
import UserStorageFSM._
// 1. define start with
startWith(Disconnected, EmptyData)
// 2. define states
when(Disconnected) {
case Event(Connect, _) =>
println("UserStorage Connected to DB")
unstashAll()
goto(Connected) using (EmptyData)
case Event(_, _) =>
stash()
stay using (EmptyData)
}
when(Connected) {
case Event(Disconnect, _) =>
println("UserStorage disconnected from DB")
goto(Disconnected) using EmptyData
case Event(Operation(op, user), oldData) =>
op match {
case DBOperation.Create =>
stay using new Data {
override def data = user :: oldData.data
}
case DBOperation.Delete => stay using new Data {
override def data = oldData.data.filter(_ != user)
}
case DBOperation.Read => {
println(oldData.data)
stay using oldData
}
case DBOperation.Update => {
stay using new Data {
override def data: List[User] = user :: oldData.data.filter(_.username != user.username)
}
}
}
stay using EmptyData
}
// 3. initialize
initialize()
}
object FiniteStateMachine extends App {
import UserStorageFSM._
val system = ActorSystem("Hotswap-FSM")
val userStorage = system.actorOf(Props[UserStorageFSM], "userStorage-fsm")
userStorage ! Connect
userStorage ! Operation(DBOperation.Create, User("Admin", "admin@packt.com"))
userStorage ! Operation(DBOperation.Create, User("Admin1", "admin@packt.com"))
userStorage ! Operation(DBOperation.Read, User("Admin", "admin@packt.com"))
userStorage ! Disconnect
Thread.sleep(1000)
system.terminate()
}
模拟一个允许CRUD操作的存储系统。这里的问题是系统似乎总是包含空数据。这里出了什么问题?
在 Operation
的处理程序中,您在 op
的模式匹配中调用 stay
,但随后在底部调用 stay using EmptyData
,这就是那个习惯了。从 case Event(Operation(op, user), oldData) =>
的底部删除 stay using EmptyData
,您应该会开始看到更新后的 Data
.