《 akka 族演员类型》中的恰当未来处理

8nuwlpux  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(141)

什么是正确的方式来处理未来从一个 akka (打字)演员?
例如,假设有一个Actor OrderActor,它接收命令来下订单......这是通过对外部服务进行http调用来完成的。由于这些是对外部服务的http调用,因此涉及到Future。那么,在Actor内部处理Future的正确方法是什么呢?
我读到一些关于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
csga3l58

csga3l581#

通常最好避免在参与者内部进行Future转换(mapflatMapforeach等)。当转换运行时,参与者内部的某些可变状态可能不是您所期望的状态。在Akka Classic中,最有害的形式可能是将回复发送到错误的参与者。
Akka Typed(特别是在函数API中)减少了大量可能导致麻烦的可变状态,但通常还是将Future作为消息发送给参与者是个好主意。
因此,如果orderFacade.placeOrder生成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和friends相比,这样做实际上没有太多的开销(两者通常都涉及在调度程序上调度一个异步执行的任务)。

相关问题