我有数据以块的形式到达actor,并希望将这些块作为 Play Result
中的流返回。因为从Ok.stream
获得响应的唯一方法看起来像是理想的候选者,所以:
Action.async { request =>
(source ? GetStream()).map {
case enumerator => Ok.stream(enumerator)
}
}
我将从我的演员返回一个Enumerator[Array[Byte]]
,然后在演员内部继续将块推入枚举器,因为消息到达演员。但是:从一个演员那里返回一个可变的枚举器肯定看起来像是某种违规行为。
有没有更合适的方法来实现这一目标?我认为akka-stream
或akka.io
可能是可能解决问题空间的抽象,但我看不出它们将如何应用。
答案 0 :(得分:0)
我已经解决的解决方案,直到建议更好的解决方案是使用ActorDSL在我的非actor调用者的上下文中捕获枚举器:
case GET(p"/stream/$streamId") => Action.async { request =>
val (enumerator, channel) = Concurrent.broadcast[Array[Byte]]
actor(new Act {
storage ! Get(streamId)
become {
case DataStart(id, parts, bytes) =>
sender() ! DataAck(id)
become {
case DataPart(_, i, b) =>
channel.push(b.toArray)
case DataEnd(_) =>
channel.eofAndEnd()
}
}
})
Ok.stream(enumerator).as("text/plain")
}
反对来自演员的返回和枚举器的论点是它是可变的和不可序列化的。但是你需要一个actor来接收一系列消息来为枚举器提供信息。通过DSL创建actor,它显式嵌入在调用上下文中,因此不存在枚举器在序列化边界内泄漏的风险。