從 Akka(型別化)Actor 內部處理 Futures 的正確方法是什么?
例如,假設有一個 ActorOrderActor接收命令來下訂單……它通過對外部服務進行 http 呼叫來實作。由于這些是對外部服務的 http 呼叫,Future因此涉及到 s。那么,Future從 Actor 內部處理該問題的正確方法是什么。
我讀了一些關于 pipeTo 模式的東西。這是這里需要發生的事情還是其他事情?
class OrderActor(context: ActorContext[OrderCommand], orderFacade: OrderFacade)
extends AbstractBehavior[OrderCommand](context) {
context.log.info("Order Actor started")
override def onMessage(msg: OrderCommand): Behavior[OrderCommand] = {
msg match {
case PlaceOrder(
referenceId: OrderReferenceId,
ticker: Ticker,
quantity: Int,
replyTo: ActorRef[OrderResult]
) =>
orderFacade
.placeOrder(ticker, quantity) //this returns a Future
.map(res => {
//transform result
//book keeping / notification (affects state)
replyTo ! transformed
//Can/Should we map like this? I tried adding a log statement in here, but I never see it... and the replyTo doesnt seem to get the message.
})
this
uj5u.com熱心網友回復:
通常最好避免在actor 內部進行Future轉換(map、flatMap、等)。foreach當轉換運行時,actor 中的某些可變狀態不是您所期望的,這是一個明顯的風險。在 Akka Classic 中,這種情況最有害的形式可能會導致向錯誤的 actor 發送回復。
Akka Typed(特別是在函式式 API 中)減少了許多可能導致麻煩的可變狀態,但通常將其Future作為訊息傳遞給 actor 仍然是一個好主意。
所以如果orderFacade.placeOrder結果是 a Future[OrderResponse],你可以添加這樣的子OrderCommand類
// also include fields from the PlaceOrder which will be useful
case class OrderResponseIs(resp: OrderResponse, replyTo: ActorRef[OrderResult]) extends OrderCommand
// TODO include fields
case class OrderFailed() extends OrderCommand
然后用管道Future傳遞給自己:
import scala.util.{ Failure, Success }
context.pipeToSelf(orderFacade.placeOrder) {
case Success(resp) => OrderResponseIs(resp, replyTo)
case Failure(_) => OrderFailed()
}
然后,您必須處理這些訊息:
case OrderResponseIs(resp, replyTo) =>
// transform resp
val transformed = ???
replyTo ! transformed
this
case OrderFailed() =>
context.log.warning("Stuff is broken")
this
與朋友相比,這樣做實際上并沒有太多開銷map(兩者通常都涉及調度任務以在調度程式上異步執行)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/453089.html
