如何避免在Scala类中保存状态?

时间:2017-03-25 17:12:07

标签: scala akka

我目前正在Scala中编写一个客户端应用程序,它向API发出HTTP请求。在这个客户端应用程序中,我实现了一个服务连接器,它封装了所有API相关逻辑。在进行API调用之前,我想验证用户身份,但我想抽象这个过程。这意味着我的actor只会调用服务连接器来启动API调用,如下所示:

class MessageProcessor(credentials: Credentials) extends Actor with ActorLogging {

  implicit val ec = context.dispatcher

  override def receive: Receive = {
    case sendMsg: SendMessage =>
      log.info(s"Sending message ${sendMsg.body}.")
      sendMessage(sendMsg)
  }

  def sendMessage(msg: SendMessage) = {
    ServiceConnector.sendMessage(credentials, msg).map { result =>
      // My result
    }

  }

}

object MessageProcessor {
  def props(credentials: Credentials) = Props(classOf[MessageProcessor], credentials)
}

在我的服务连接器中,我想以某种方式 保存 “Scala方式”JWT令牌,如果我尚未通过身份验证,请在创建之前发送身份验证请求实际的API调用。

如何在考虑到期货的情况下以不可变的方式编写此类服务?

我考虑过创建其他演员并只使用令牌发送消息,但这是否真的有必要?

2 个答案:

答案 0 :(得分:2)

你需要多个Akka状态来做正确的" Scala方式"。我不完全确定您的API是如何工作的,但以下示例显示了一种基本方法。在其第一个状态中,它在发送消息之前进行身份验证。确认身份验证后,它会发送消息。以下所有消息都会立即发送。如果以某种方式丢失了身份验证,您还可以添加一个注销或超时情况,切换回第一个接收状态。

class MessageProcessor(credentials: Credentials) extends Actor with ActorLogging {

  implicit val ec = context.dispatcher

  override def receive: Receive = {
    case sendMsg: SendMessage =>
      log.info(s"Authenticating...")
      sender ! NotAuthenticated(credentials) // or authenticate somehow
      context become waitingAuthentication(sendMsg)
  }

  def waitingAuthentication(sendMsg: SendMessage): Receive = {
    case _: AuthenticationConfirmation =>
      log.info(s"Sending message ${sendMsg.body}.")
      sendMessage(sendMsg)
      context become authenticated
  }

  def authenticated: Receive = {
    case sendMsg: SendMessage =>
      log.info(s"Sending message ${sendMsg.body}.")
      sendMessage(sendMsg)
  }

}

它只是一个示例,并没有考虑所有情况(例如,在等待身份验证期间SendMessage,因此您需要一个SendMessages的队列。如果多个actor需要知道身份验证状态或凭据,那么如果您不想要一个处理和验证所有消息的瓶颈角色,则需要向他们广播。在这种情况下,所有这些都需要多个身份验证状态,如上所述。

答案 1 :(得分:0)

演员是为州设计的

这似乎是一种虚假的运动。 Actors的全部意义在于他们可以仓库状态。来自documentation specifically on state

  

好消息是,Akka演员在概念上各有自己的   轻质螺纹,完全与其余部分隔离   系统。这意味着不必使用同步访问   锁定你可以编写你的演员代码而不用担心   并发性。

因此,“scala方式”只是将它保存在Actors中的变量中。

使用Actors而不是Futures的原因之一是你可以保持状态。为什么选择演员然后解雇他们的主要优势之一???

你的问题相当于“如何在不进行散列的情况下使用HashMap(以scala方式)?”