Akka Streams + Akka Http Pass参数通过流程

时间:2017-02-20 20:27:45

标签: scala akka akka-stream akka-http

我有以下代码段:

    case class SomeClass(param1:String,param2:String,param3:String)

    val someClassActorSource: Source[SomeClass, ActorRef] = Source
      .actorPublisher[SomeClass](Props[SomeClassActorPublisher])

    val someFlow: ActorRef = Flow[SomeClass]

        .mapAsync(3)(f=> getDocumentById(f))

        .map(f =>{
          val request = HttpRequest(method = HttpMethods.POST, uri = "http://localhost:8000/test")
            .withEntity(ContentTypes.`text/xml(UTF-8)`, ByteString(f.a)
            )
          (request,request)

        }).via(connection)

        //Parsing Response
        .mapAsync(3){
          case (Success(HttpResponse(status, _, entity, _)),request)=>
            entity.dataBytes.runFold(ByteString(""))(_ ++ _)
        }
        .map(resp =>parse(resp.utf8String,?????????????) )
        .to(Sink.someSink{....})
        .runWith(someClassActorSource)

    def parse(resp:String,parseParam:String)=????

在代码中的某处我向Flow发送消息:

someflow ! SomeClass("a","b","c")
someflow ! SomeClass("a1","b1","c1")

我的问题是方法解析应该使用原始案例类

中的param2

因此,对于第一条消息,它应该是

  parse(response,"b")

,对于第二条消息,它应该是

  parse(response,"b1")

所以问题是,如何从我提交给流程的方法中获取参数?

1 个答案:

答案 0 :(得分:1)

假设您的connection值正在通过

实例化
val connection = Http().cachedHostConnectionPool(...)

您可以使用Connection接受元组的事实,而不是简单地在元组中传递request两次,您可以传入输入的SomeClass。此SomeClass实例必须遍历每个Flow值才能进入解析阶段。

稍微修改一下代码:

val getDocumentFlow = 
  Flow[SomeClass].mapAsync(3)(f => getSomDocumentById(f).map( d => d -> f))

您的问题没有说明getDocumentById的退货类型,所以我只是使用Document

val documentToRequest = 
  Flow[(Document, SomeClass)] map { case (document, someClass) =>
    val request = ...

    (request, someClass)
  }

val parseResponse = 
  Flow[(Try[HttpResponse], SomeClass)].mapAsync(3){
    case (Success(HttpResponse(status, _, entity, _)), someClass) =>
      entity
        .dataBytes
        .runFold(ByteString(""))(_ ++ _)
        .map(e => e -> someClass)
  }

val parseEntity = Flow[(ByteString, SomeClass)] map { 
  case (entity, someClass) => parse(entity.utf8String, someClass)
}

然后可以按照问题中的描述使用这些流程:

val someFlow = 
  someClassActorSource
    .via(getDocumentFlow)
    .via(documentToRequest)
    .via(connection)
    .via(parseResponse)
    .via(parseEntity)
    .to(Sink.someSink{...})
    .run()