喷死信消息

Spray Dead Letter msg

我正在尝试执行以下代码

trait CustomHttpService extends HttpService {

  import MyJsonProtocol._
  import spray.httpx.SprayJsonSupport._

  implicit def executionContext = actorRefFactory.dispatcher
  implicit val timeout = Timeout(5 seconds)

  val offerActor = actorRefFactory.actorOf(Props[OfferActor], "offer-actor")

  val defaultRoute = {
    path("offer" / JavaUUID) { uuid =>
      get {
        respondWithMediaType(`application/json`) {
          complete {
            (offerActor ? Get(uuid)).mapTo[Offer]
          }
        }
      }
    }
  }
}

class OfferActor extends Actor {
  override def receive = {
    case Get(id) =>
      val future = OfferService.genericService.getById(id)
      future.onComplete {
        case Success(s) =>
          s match {
            case Some(offer) => sender ! offer
            case None => println("none")
          }
        case Failure(f) => f
      }
    case id: String => println("received string id: " + id)
    case _ => println("receive nothing")
  }
}

最初我试图 return 直接未来,但它给了我一个错误,抱怨我试图投射到我的 Offer 对象的承诺。

然后我只是丑陋地解决了我在演员内部的未来,最终获得了报价,然后 return 将其发送给发件人。

这样做我得到以下信息:

[06/09/2015 15:16:43.056] [spray-system-akka.actor.default-dispatcher-4] [akka://spray-system/deadLetters] Message [com.spray.entity.Offer] from Actor[akka://spray-system/user/spray-actor/offer-actor#-617290326] to Actor[akka://spray-system/deadLetters] was not delivered. [2] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

确实,我正在发送一条消息,其中包含我从数据库中获得的报价。

相反,如果我只是像这样创建一个报价,效果很好。

case Get(id) => sender ! Offer(Some(id), "offer", new DateTime())

我相信 actor 内部的 future.onComplete 导致了错误。

有什么想法吗?

好吧,刚刚解决了它试图阻止我的未来。

我刚刚创建了一个被屏蔽的版本

OfferService.genericService.getByIdBlocking(id)

我用

屏蔽了它
Await.result

成功了!

所以基本上我不得不让 akka 使用 ask 模式接受我的呼叫,但在 actor 内部进行阻塞操作。

sender 实际上是一个函数,因此您可以编写 sender() 来表明它不仅仅是访问不可变值。当您在 future.onComplete 中调用 sender 时,sender 的值不再有效。

我之前 运行 遇到过这个问题,我的解决方法是将 sender 的值保存在未来之外:

class OfferActor extends Actor {
  override def receive = {
    case Get(id) =>
      val future = OfferService.genericService.getById(id)
      val replyTo = sender
      future.onComplete {
        case Success(s) =>
          s match {
            case Some(offer) => replyTo ! offer
            case None => println("none")
          }
        case Failure(f) => f
      }
    case id: String => println("received string id: " + id)
    case _ => println("receive nothing")
  }
}