如何在akka中使用askpattern.ask( java /Kotlin)

fcipmucu  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(524)

我在使用akka输入的ask模式时遇到了一些问题。我正在尝试从演员外部发送消息,并尝试遵循此示例。但是,我认为我的设置与示例有点不同:

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()

我想发一封信 StartSimulation 邮件收件人 SimulatorManager 从演员系统之外。然而,我被困在什么输入的 replyTo 函数参数。

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!>! ,但我不知道如何创建这样的函数。任何帮助都将不胜感激!!

dbf7pr2w

dbf7pr2w1#

这个 replyTo -> 函数构造要发送的消息,并向将接收消息的参与者注入引用。
这是因为,为了实现异步,ask模式有效的作用是:
向某个参与者发送消息(称之为“a”)
产生一个参与者(参与者“b”),其唯一目的是接收回复并用该回复完成未来(或者如果达到超时,则失败该未来);参与者“b”在收到消息或超时后立即停止)
在经典的(非类型化的)akka中,消息将由接收者确定 sender 因此,ask模式非常简单(不过,当从参与者发送ask时,您必须小心由此产生的未来:基本上,您可以做的唯一安全的事情就是调整消息并将其传输到您的邮箱)。
在akka打字,因为 ActorRef 现在控制可以发送的消息, sender 不可用。因此,现在必须显式地对组成协议的消息中预期回复的类型进行建模。
在这里我承认这是我写的第一个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` 最终将完成与 `GradebookIs` 信息 `gradebookRouter` 我使用这种措辞是因为 `replyTo` 这有助于将作品委托给另一个演员:你也可以在《阿克卡经典》中这样做,但保留发送者有一些微妙之处(这很容易搞砸)。

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

免责声明:java/kotlin的类型系统相对于scala的微妙之处(例如协方差/逆变)可能会使代码无法工作,但我希望它能让事情变得相当清楚。
热释光;dr:确保邮件中的字段可以作为回复地址。它们不需要命名 `replyTo` ,尽管这绝对是一个惯例。

相关问题