Scala Akka Typed -在带有ask的行为内发送请求

oaxa6hgo  于 2022-11-06  发布在  Scala
关注(0)|答案(1)|浏览(210)

我有点新akka打字,我正试图发送一个消息,需要在给定时间内回答.
我发现了带有ask的请求-响应模式,这看起来很有趣,但是有没有一种方法可以在已经定义的Behaviours.receive中实现它?
这里的想法是在每次玩家应答时或超时后调用nextPlayerTurn

override def refereeTurn(): Behavior[Msg] = Behaviors.receive {
   case (_, msg: GuessMsg) =>
      if(currentPlayer.isDefined && currentPlayer.get == msg.getSender) {
        controller ! msg
      } else {
        println("Player tried to guess after Timeout")
      }
      Behaviors.same
  case (context, msg: ReceivedResponseMsg) =>
      if(currentPlayer.isDefined && currentPlayer.get == msg.getSender) 
        nextPlayerTurn(context)     
      Behaviors.same
      ...
}

...

/**
   * Tells to a player to start his turn and sets a timer that defines time in which a player has to make a guess.
   * If such guess isn't made, sends that user an end turn message, fails the promise of his turn and allows next
   * player to play his turn

* /

  override def nextPlayerTurn(ctx: ActorContext[Msg]): Unit = {
    implicit val timeout: Timeout = Timeout.timeout
    currentPlayer = Option(turnManager.nextPlayer)
    ctx.ask[Msg,Msg](currentPlayer.get, ref => YourTurnMsg(ref)) {
      case Success(msg: GuessMsg) => println("\n SUCCESS"); msg
      case Failure(_) => println(currentPlayer.get +" didn't guess in time"); TurnEnd(currentPlayer.get)
      case _ => TurnEnd(currentPlayer.get)
    }
  }

在这种情况下,在发送YourTurnMsg后,玩家应该使用停止计时器的GuessMsg进行响应,这从未发生,因为正在执行refereeTurn Begaviour内部的大小写匹配,而不是Success(而在超时后总是给出Failure)。
我是不是对询问模式有了错误的想法,应该用计时器来做一个新的行为?

2uluyalo

2uluyalo1#

如果你想使用ask模式,那么处理结果的代码需要向主参与者发送一条消息,而不是直接尝试进行任何处理。你可以根据结果发送不同的消息,或者只发送原始结果并在参与者中进行处理,但是你不能在该代码中执行任何依赖于参与者状态的操作,因为它可能在不同的线程上运行。
但是ask并不便宜,所以在这种情况下,似乎最好只设置一个计时器,看看哪个消息先回来。

相关问题