使用flatMapConcat时,如何检测到子流被处理?

时间:2016-06-22 12:33:16

标签: scala akka akka-stream

最近我问的是以下问题的发展: How do I dynamically add Source to existing Graph?

假设您有元素Source[T, NotUsed]的源队列。您通过.offer()调用放置了子流。使用flatMapConcat

时,如何检测到子流已完全处理?

我尝试将Promise[T]放在子流的末尾,但没有保证在它之前的元素不会被处理得更慢。这是演示问题的代码

trait PipeElement
case class Link(url: String) extends PipeElement
case class Ids(ids: List[Int]) extends PipeElement
case class Title(text: String) extends PipeElement
case class Completion(p: Promise[Unit]) extends PipeElement

val (queue, completionFut) = Source
  .queue[Source[PipeElement, NotUsed]](10, backpressure)
  .flatMapConcat(identity)
  .buffer(2, OverflowStrategy.backpressure)
  .mapAsync(4) {
    case Link(url) => Future{
      Thread.sleep(500)
      Some("url: " + url)
    }
    case Ids(ids) => Future{
      Some("ids: " + ids)
    }
    case Title(title) => Future{
      Some("title: " + title)
    }
    case Completion(p) =>
      p.success(Unit)
      Future.successful(Some("Promise delivered"))
  }
  .toMat(Sink.foreach(println))(Keep.both)
  .run()

val promise = Promise[Unit]()
val lst = List(Link("Link"), Ids(List(1,2,3)), Title("title"), Completion(promise))
queue.offer(Source(lst))
queue.offer(Source(List(Link("Link2"), Link("Link3"))))
queue.complete()

promise.future.onComplete {
  case Success(res) =>
    println("promise: " + res)
    // system.terminate()
  case Failure(ex) =>
    ex.printStackTrace()
    system.terminate()
}

completionFut.onComplete {
  case Success(res) =>
    println("Stream is finished: " + res)
    system.terminate()
  case Failure(ex) =>
    ex.printStackTrace()
    system.terminate()
}

Await.result(system.whenTerminated, Duration.Inf)

输出

promise: ()
Some(url: Link)
Some(ids: List(1, 2, 3))
Some(title: title)
Some(Promise delivered)
Some(url: Link2)
Some(url: Link3)
Stream is finished: Done

我可以通过从Either[Promise[Unit], String]返回mapAsync然后过滤/收集此类元素来解决此问题

.collect {
  case Left(p) if {
    p.success(Unit)
    false
  } => ???
  case Right(v) => v
}

它有效,但对我来说看起来太黑了:))

想法?

0 个答案:

没有答案