[英]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 模式有效地做的是:
在经典(无类型)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.