簡體   English   中英

如何停止處理 akka 流中的其他元素?

[英]How to stop processing further elements in akka streams?

我有一個整數列表 {2,4,6,8,9,10,12}

為了簡化我的問題,我的目標是獲取所有偶數,直到遇到奇數。 所以我的結果應該是 -> {2,4,6,8, 9}

另外,我有一個演員說一個數字是偶數還是奇數(為簡單起見)

我做了以下事情:-

CompletionStage<List<Integer>> result = Source.from(integerList)
      .ask(oddEvenActor, OddEvenResponse.class, Timeout.apply(1, TimeUnit.SECONDS))
      .map(oddEvenResult -> if(oddEvenResult.isOdd()){
                                //stop processing further elements
                            }
                            else {
                                return oddEvenResult.number();
                            })
     .runWith(Sink.seq(), materializer)

那么,一旦我遇到一個奇怪的元素,我怎樣才能停止對其他元素的處理呢?

一旦 stream 完成,CompletionStage “結果”應該包含 2,4,6,8,9。

I checked out the statefulMapConcat ( https://doc.akka.io/docs/akka/current/stream/operators/Source-or-Flow/statefulMapConcat.html ) However, this will still process the other elements after 9 as the actor仍然會被“問”

當然,我可以執行以下操作:-

  1. 有一個 resultList 變量(全局),我做一個 resultList.add(oddEvenResult.number()) ,然后在遇到奇數時拋出異常。 我必須編寫一個自定義異常 class 來捎帶這個全局結果列表。

  2. 按照@Jeffrey Chung 的建議使用 takeWhile,但 OddEvenActor 仍然被“要求”處理元素 10 和 12。這是沒有意義的。

有沒有更清潔的方法來實現這一目標?

使用takeWhile 在 Scala 中,這將類似於以下內容:

implicit val timeout: akka.util.Timeout = 3.seconds

val result: Future[Seq[Int]] =
  Source(List(2, 4, 6, 8, 9, 10, 12))
    .ask[OddEvenResponse](oddEvenActor)
    .takeWhile(resp => !resp.isOdd, true)
    .map(_.number)
    .runWith(Sink.seq)

請注意在調用takeWhile時使用inclusive boolean 標志,如果您想保留第一個奇數,這是必要的。

Java 等效項看起來相似。

如果您想保留您的演員,您可以實現它,例如如下(在 Scala 中):

implicit val system = ActorSystem("StopOnOdd")
implicit val materializer = ActorMaterializer()

class StopOnOdd extends Actor with ActorLogging {
  override def receive: Receive = {
    case x: Int if x % 2 == 0 =>
      log.info(s"Just received an even int: $x")
      sender() ! x
    case x: Int if x % 2 == 1 =>
      log.info(s"Just received an odd number: $x Stop processing.")
      context.become(dontProcess)
    case _ =>
  }

  private def dontProcess: Receive = {
    case x =>
      log.info(s"Dropping $x because odd number was received.")
    }
  }


  def main(args: Array[String]): Unit = {
  val stopOnOdd = system.actorOf(Props[StopOnOdd], "simpleActor")

  val source = Source(List(2,4,6,8,9,10,12))
  implicit val timeout: Timeout = Timeout(2.seconds)
  val stopOnOddFlow = Flow[Int].ask[Int](parallelism = 1)(stopOnOdd)

  source.via(stopOnOddFlow).to(Sink.foreach[Int](number => println(s"Got number: $number"))).run()
}

output 是:

[INFO] [07/29/2020 16:37:14.618] [StopOnOdd-akka.actor.default-dispatcher-4] 
[akka://StopOnOdd/user/simpleActor] Just received an even int: 2
Got number: 2
[INFO] [07/29/2020 16:37:14.625] [StopOnOdd-akka.actor.default-dispatcher-2] 
[akka://StopOnOdd/user/simpleActor] Just received an even int: 4
Got number: 4
Got number: 6
[INFO] [07/29/2020 16:37:14.627] [StopOnOdd-akka.actor.default-dispatcher-4] 
[akka://StopOnOdd/user/simpleActor] Just received an even int: 6
Got number: 8
[INFO] [07/29/2020 16:37:14.627] [StopOnOdd-akka.actor.default-dispatcher-4] 
[akka://StopOnOdd/user/simpleActor] Just received an even int: 8
[INFO] [07/29/2020 16:37:14.628] [StopOnOdd-akka.actor.default-dispatcher-4] 
[akka://StopOnOdd/user/simpleActor] Just received an odd number: 9 Stop processing.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM