为什么这个 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.