有条件地使用akka流跳过流

时间:2015-11-20 01:00:53

标签: akka akka-stream akka-http

我正在使用akka流,我有一段我的图表需要有条件地跳过,因为流程无法处理某些值。具体来说,我有一个获取字符串并发出http请求的流,但是当字符串为空时,服务器无法处理这种情况。但我需要返回一个空字符串。有没有办法做到这一点,而不必通过http请求知道它会失败?我基本上有这个:

val source = Source("1", "2", "", "3", "4")
val httpRequest: Flow[String, HttpRequest, _]
val httpResponse: Flow[HttpResponse, String, _]
val flow = source.via(httpRequest).via(httpResponse)

我唯一能想到的就是在我的httpResponse流程中捕获400错误并返回默认值。但是我希望能够避免因为我知道事先会失败的请求而点击服务器的开销。

2 个答案:

答案 0 :(得分:15)

您可以使用flatMapConcat

(警告:从未编译,但你会得到它的要点)

val source = Source("1", "2", "", "3", "4")
val httpRequest: Flow[String, HttpRequest, _]
val httpResponse: Flow[HttpResponse, String, _]
val makeHttpCall: Flow[HttpRequest, HttpResponse, _]
val someHttpTransformation = httpRequest via makeHttpCall via httpResponse
val emptyStringSource = Source.single("")
val cleanerSource = source.flatMapConcat({
  case "" => emptyStringSource
  case other => Source.single(other) via someHttpTransformation
})

答案 1 :(得分:13)

Viktor Klang的解决方案简明扼要,elegant。我只是想用Graphs来演示另一种选择。

您可以将字符串源拆分为两个流,并为有效字符串过滤一个流,为无效字符串过滤另一个流。然后合并结果(" cross the streams")。

基于documentation

val g = RunnableGraph.fromGraph(FlowGraph.create() { implicit builder: FlowGraph.Builder[Unit] =>
  import FlowGraph.Implicits._

  val source = Source(List("1", "2", "", "3", "4"))
  val sink : Sink[String,_] = ???

  val bcast = builder.add(Broadcast[String](2))
  val merge = builder.add(Merge[String](2))

  val validReq =   Flow[String].filter(_.size > 0)
  val invalidReq = Flow[String].filter(_.size == 0)

  val httpRequest: Flow[String, HttpRequest, _] = ???
  val makeHttpCall: Flow[HttpRequest, HttpResponse, _] = ???
  val httpResponse: Flow[HttpResponse, String, _] = ???
  val someHttpTransformation = httpRequest via makeHttpCall via httpResponse

  source ~> bcast ~> validReq ~> someHttpTransformation ~> merge ~> sink
            bcast ~>      invalidReq                    ~> merge
  ClosedShape
})

注意:此解决方案会拆分流,因此Sink可能会处理字符串值结果的顺序与基于输入的预期顺序不同。