如何将ExecutionContext传递给喷涂路径或更好地避免询问和使用tell

时间:2015-03-12 17:08:16

标签: scala akka spray

当我收集Spray.io的经验时,我发现有更多方法可以解决这个问题。我发现了一些有时相互矛盾的意见。所以我想请更有经验的用户分享他们的观点。 基本上有一个REST api和分离的服务层都通过蛋糕模式组装如下:

object Main extends App with BootedCore with ServiceActors with RestApi with Web

ServiceActors将ActorRefs保存到各种服务,RestApi保存Spray路由。服务参与者回复案例类。

问题是如何连接这两层?

**可能性1 - 使用akka ask pattern **

  import scala.concurrent.ExecutionContext.Implicits.global
  //TODO: Excecution context - this is not scalable
  val adServiceRoute: Route = {
    path("service" / "import" / "status") {
      get {
        respondWithMediaType(`text/plain`) {
          complete {
            adImporterService.ask(GetImportStatus)(1 second).mapTo[StatusOfImport]
          }
        }
      }
    }
  }

  implicit val importStatusMarshaller: Marshaller[StatusOfImport] =
    Marshaller.of[StatusOfImport](ContentTypes.`text/plain`) { (value, contentType, ctx) =>
      val string = "Hello marshalled status"
      ctx.marshalTo(HttpEntity(contentType, string))
    }

我找到了这个解决方案的一些缺点,我想澄清一下。 - 各种博客蛤蜊问问模式最好避免,如果可能,一些例子推理:例如它隐藏了潜在的错误等。 - 不确定要运行哪个ExcecutionContext。 Import global绝对是正确的。我有的是ActorSystem。为此目的配置分离的调度程序是否常见?

可能性2 - 使用告诉 我试图重写前一个,但无法使其正常工作

 val adServiceRoute: Route = {
    path("service" / "ad" / "import" / "status") {
      get {
        respondWithMediaType(`text/plain`) (getServiceStatus)
      }
    }
  }

  implicit val importStatusMarshaller: Marshaller[StatusOfImport] =
    Marshaller.of[StatusOfImport](ContentTypes.`text/plain`) { (value, contentType, ctx) =>
      val string = "Hello marshalled status"
      ctx.marshalTo(HttpEntity(contentType, string))
    }

  def getServiceStatus(ctx: RequestContext): Unit = {
        adImporterService.tell(GetImportStatus , ctx.responder)
  }

这里的问题是adImporterService的响应是StatusOfImport,响应者不知道如何处理。为了将响应转换为HttpResponse而创建一个每个请求的actor,只是为了处理响应,在我看来是过度的。

我显然遗漏了一些重要的事情。 有人可以更有经验澄清吗?

1 个答案:

答案 0 :(得分:0)

我认为你可以使用spray的onComplete指令。例如:

onComplete(adImporterService.ask(GetImportStatus).mapTo[StatusOfImport]) {
  case Success(v) => complete(v)
  case Failure(e) => ...
}