繁体   English   中英

如何在 Akka Typed 中使用 AskPattern.ask? (Java/科特林)

[英]How to use AskPattern.ask in Akka Typed? (Java/Kotlin)

我在使用 Akka Typed 中的 Ask Pattern 时遇到了一些麻烦。 我正在尝试从演员外部发送消息,并尝试遵循此示例 但是,我认为我的设置与示例有点不同:

object SimulatorManager {

    fun create(): Behavior<SimulatorManagerMessage> {
        val state = ... // initialize state
        return waitingToStartSimulation(state)
    }

    private fun waitingToStartSimulation(state: SimulatorManagerState): Behavior<SimulatorManagerMessage> {
        return Behaviors.receive { context, message ->
            when (message) {
                is StartSimulation -> {
                    // start simulation and update state
                    waitingToStartSimulation(state)
                }
                else -> Behaviors.same()
            }
        }
    }
}

sealed class SimulatorManagerMessage

data class StartSimulation(
    val consumer: ConsumerCredentials,
    val storeId: Long,
    val itemId: Long,
    val simTimeIncrement: Double,
    val realTimeIncrement: Double,
) : SimulatorManagerMessage()

我正在尝试从 Actor System 外部向SimulatorManager发送StartSimulation消息。 但是,我一直在为replyTo function 参数输入什么问题。

class SimulatorController(
    val systemRef: ActorSystem<SimulatorManagerMessage>,
    private val simManagerRef: ActorRef<SimulatorManagerMessage>
) {

    fun startSimulation(request: StartSimulationRequest) {
        val msg = request.toMessage()
        val result = AskPattern.ask<SimulatorManagerMessage, SimulatorController>(
            simManagerRef,
            { replyTo ->  },        // what should go here? 
            Duration.ofSeconds(15),
            systemRef.scheduler()
        )
    }
}

它说参数的类型应该是Function<ActorRef<SimulatorController,>!, SimulatorManagerMessage!>! ,但我不知道如何 go 关于创建这样的 function 。 任何帮助,将不胜感激!!

replyTo -> function 构造要发送的消息并注入对将接收消息作为回复的参与者的引用。

这是因为,为了实现异步,ask 模式有效地做的是:

  • 向某个演员发送消息(称其为“A”)
  • 生成一个演员(演员“B”),其唯一目的是接收回复并使用该回复完成未来(或者如果达到超时,则使未来失败;演员“B”将在收到消息后立即停止或暂停)

在经典(无类型)Akka 中,消息将被构造,接收者可以确定每条消息的sender ,因此询问模式非常简单(尽管,当从演员发送询问时,您必须小心结果未来:基本上,您可以做的唯一安全的事情是将消息和 pipe 调整到您的邮箱)。

在 Akka Typed 中,因为ActorRef现在控制可以发送哪些消息,所以sender不可用。 所以现在你必须在组成协议的消息中明确 model 预期回复的类型。

这是我承认这是我写的第一个 Kotlin 的地方,但你可能有类似的东西:

sealed class GradebookCommand

data class GetGradeFor(val student: String, val replyTo: ActorRef<GradeForStudent>): GradebookCommand()

data class GradeForStudent(val student: String, val score: Int, val outOf: Int)

sealed class GradebookRouterCommand

data class GetGradebookActorFor(val classId: String, val replyTo: ActorRef<GradebookIs>): GradebookRouterCommand()

data class GradebookIs(val classId: String, val gradebookActor: ActorRef<GradebookCommand>)

所以假设gradebookRouter是一个ActorRef<GradebookRouterCommand> ,你会问

val classId: String = "asdf"
val gradebookFuture: CompletionStage<GradebookIs> =
  AskPattern.ask<GradebookRouterCommand, GradebookIs>(
    gradebookRouter,
    { replyTo -> GetGradebookActorFor(classId, replyTo) },
    Duration.ofSeconds(15),
    systemRef.scheduler
  )

gradebookFuture最终将使用gradebookRouter导致发送回复的GradebookIs消息完成(我使用该措辞是因为,明确replyTo的好处之一是它有助于将工作委派给另一个参与者:您可以在 Akka 中做到这一点经典也是,但在保留发件人方面有一些微妙之处,这很容易搞砸)。

// This is perhaps where my Kotlin/Java futures code goes off the rails
val student: String = "Parry Hotter"
val gradeFuture: CompletionStage<GradeForStudent> =
  gradebookFuture.thenComposeAsync({ gradebook ->
    AskPattern.ask<GradebookCommand, GradeForStudent>(
      gradebook,
      { replyTo -> GetGradeFor(student, replyTo) },
      Duration.ofSeconds(15),
      systemRef.scheduler
    )})

免责声明:Java/Kotlin 类型系统相对于 Scala 的微妙之处(例如,围绕协变/逆变)可能会使该代码不起作用,但我希望它可以使事情变得相当清晰。

TL;DR:确保在您的消息中包含用作回复地址的字段。 它们不必命名为replyTo ,尽管这绝对是一种惯例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM