简体   繁体   English

Akka Streams takeWhile 处理下一个元素,即使条件失败

[英]Akka Streams takeWhile processing next element even after condition fails

I have a very simple actor that just prints the number:-我有一个非常简单的演员,只打印数字:-

public class PrintLineActor extends AbstractLoggingActor {

  @Override
  public Receive createReceive() {
    return receiveBuilder()
        .match(Integer.class, i -> {
          System.out.println("Processing: " + i);
          sender().tell(i, self());
        }).build();
  }
}

Now, I have a stream to print the even numbers until I encounter an odd element:-现在,我有一个 stream 来打印偶数,直到遇到奇数元素:-

  @Test
  public void streamsTest() throws Exception {

    ActorSystem system = ActorSystem.create("testSystem");
    ActorRef printActor = system.actorOf(Props.create(PrintLineActor.class));

    Integer[] intArray = new Integer[]{2,4,6,8,9,10,12};
    CompletionStage<List<Integer>> result = Source.from(Arrays.asList(intArray))
        .ask(1, printActor, Integer.class, Timeout.apply(10, TimeUnit.SECONDS))
        .takeWhile(i -> i != 9)
        .runWith(Sink.seq(), ActorMaterializer.create(system));

    List<Integer> result1 = result.toCompletableFuture().get();
    System.out.println("Result :- ");
    result1.forEach(System.out::println);
  }

I do NOT expect any element after 9 being processed aka being sent to actor.不希望在处理 9 之后的任何元素也被发送给演员。 However, I see the number "10" also being processed by actor (but not 12) as seen in below output但是,我看到演员(但不是 12)也在处理数字“10”,如下面的 output

Processing: 2
Processing: 4
Processing: 6
Processing: 8
Processing: 9
Processing: 10 //WHY IS THIS BEING PROCESSED BY ACTOR??

Result :- 
2
4
6
8

Why is 10 being processed by actor?为什么演员要处理10? How to stop this?如何阻止这种情况?

EDIT:编辑:

I have tried debugging by recording timestamp of events, just to see if 10 is being processed before 9 actually completes, but no, 10 is taken after 9 is processed fully.我已经尝试通过记录事件的时间戳来进行调试,只是为了查看是否在 9 实际完成之前处理了 10,但是不,在完全处理 9 之后获取 10。 here are the logs:-这是日志:-

Before Ask: 2 in 1596035906509
Processing inside Actor: 2 at 1596035906509
Inside TakeWhile 2 at  in 1596035906509

Before Ask: 4 in 1596035906609
Processing inside Actor: 4 at 1596035906610
Inside TakeWhile 4 at  in 1596035906610

Before Ask: 6 in 1596035906712
Processing inside Actor: 6 at 1596035906712
Inside TakeWhile 6 at  in 1596035906712

Before Ask: 8 in 1596035906814
Processing inside Actor: 8 at 1596035906814
Inside TakeWhile 8 at  in 1596035906815

Before Ask: 9 in 1596035906915
Processing inside Actor: 9 at 1596035906915
Inside TakeWhile 9 at  in 1596035906916

Before Ask: 10 in 1596035907017 //so 10 is taken much after the 9 is processed fully
Processing inside Actor: 10 at 1596035907017

Result :- 
2
4
6
8

Also, if i replace the.ask with a direct.map(print..), then 10 does not get printed.此外,如果我用 direct.map(print..) 替换 the.ask,则不会打印 10。 So why this happens when actor.ask is involved is very strange to me.所以当涉及actor.ask时为什么会发生这种情况对我来说很奇怪。

Because you ask printActor asynchronously rather than print synchronously.因为您异步ask printActor 而不是同步打印。 In your exact run:在您的确切运行中:

  • message 9 arrives at PrintActor, prints "Processing: 9"消息 9 到达 PrintActor,打印“Processing: 9”
  • message 10 arrives at PrintActor, prints "Processing: 10"消息 10 到达 PrintActor,打印“Processing: 10”
  • Your Akka stream receives the response message for message 9 from PrintActor, complete the Akka stream, therefore in the result there is neither 9 nor 10. Your Akka stream receives the response message for message 9 from PrintActor, complete the Akka stream, therefore in the result there is neither 9 nor 10.

To solve the exact problem, remove the async ask and print synchronously instead.要解决确切的问题,请删除异步询问并改为同步打印。 But not sure if PrintActor is just an analogy, let me know.但不确定 PrintActor 是否只是一个类比,请告诉我。

The akka streams are buffering the values thru the different streams. akka 流通过不同的流缓冲值。 Please note that 10 was precessed, but it is not part of the result.请注意,10 已被处理,但它不是结果的一部分。 If you wish, you can configure the buffer size:如果您愿意,可以配置缓冲区大小:

.ask(1, printActor, Integer.class, Timeout.apply(10, TimeUnit.SECONDS)).buffer(1, OverflowStrategy.backpressure)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM