急切地停止Akka-Stream Source

时间:2017-05-18 12:40:42

标签: akka-stream

我有以下(简化)消费者应该在第一个项目之后取消Akka-Stream(今天的2.11_2.5-SNAPSHOT)Source,但onNext仍然被调用4次:

static Subscriber<Object> println() {
    return new Subscriber<Object>() {

        Subscription s;

        int n;

        @Override
        public void onSubscribe(Subscription s) {
            this.s = s;
            s.request(5);
        }

        @Override
        public void onNext(Object t) {
            System.out.println(Thread.currentThread().getName() 
                  + ": " + t + " - " + (++n));
            if (s != null) {
                s.cancel();
                s = null;
            }
        }

        @Override
        public void onError(Throwable t) {
            t.printStackTrace();
        }

        @Override
        public void onComplete() {
            System.out.println(Thread.currentThread().getName() + ": DONE");
        }
    };
}

public static void main(String[] args) throws Exception {
    Config cfg = ConfigFactory.parseResources(
        AkkaRange.class, "/akka-streams.conf").resolve();
    ActorSystem actorSystem = ActorSystem.create("sys", cfg);

    ActorMaterializer materializer = ActorMaterializer.create(actorSystem);

    Source<Integer, NotUsed> source = Source.repeat(1);

    Publisher<Integer> p = source.runWith(Sink.asPublisher(
         AsPublisher.WITH_FANOUT), materializer);

    p.subscribe(println());

    Thread.sleep(1000);

    actorSystem.terminate();
}

鉴于请求是5,但只进行了4次调用,我假设底层消息传递体系结构在检查消息队列中是否有取消(或进一步请求)消息之前,以4批次响应请求。

是否有设置让更频繁地取消?

用例类似于 interop 计算,其中存在计算密集的阶段(映射),其可以在1-2个源元素之后产生期望的结果并且下游在这种情况下取​​消流。问题在于,由于这4个批次,对剩余的2-3个元素也执行了计算。

1 个答案:

答案 0 :(得分:0)

Subscriber接口是a part of Reactive Streams规范,其中包含许多库,包括akka-streams。此规范陈述了以下内容:

  

如果仍有请求的元素未决,则订阅者必须准备好在调用Subscription.cancel()之后接收一个或多个onNext信号[见3.12]。 Subscription.cancel()不保证立即执行基础清理操作。

因此,您必须手动处理订户中的这种情况,否则将违反规范,因此不适合与实施规范的库一起使用。