简体   繁体   English

如何创建一个从 akka-stream 源订阅开始的 Flow.Publisher

[英]How to create a Flow.Publisher that starts on subscribe from an akka-stream Source

I have a java interface that I have to implement that looks like that:我有一个 java 接口,我必须实现它,如下所示:

public Flow.Publisher<Packet> getLivePublisher();

This interface must return a Flow.Publisher that stays inactive until it is subscribed to, and the subscriber calls Subscription.next(n) .此接口必须返回一个Flow.Publisher ,它在被订阅之前保持不活动状态,并且订阅者调用Subscription.next(n)

So far, my implementation looks like到目前为止,我的实现看起来像

return Source
    .fromIterator(() -> new LivePacketIterator())
    .async("live-dispatcher")
    .runWith(JavaFlowSupport.Sink.asPublisher(AsPublisher.WITHOUT_FANOUT), actorSystem);

Unfortunately, this seems to immediately start getting elements from my LivePacketIterator , even when no subscribers ahve subscribed to the returned Flow.Publisher .不幸的是,这似乎立即开始从我的LivePacketIterator获取元素,即使没有订阅者订阅返回的Flow.Publisher

I understand that a Source is just a sort of a template for a Subscribable source of objects (my understanding is that it's like a Factory of Publishers), and that it only converts to a concrete active source once it's materialized.我知道Source只是对象的可订阅源的一种模板(我的理解是它就像一个出版商工厂),并且它只有在具体化后才会转换为具体的活动源。 So if I understand correctly, I need to somehow materialize my Source to get a Flow.Publisher .因此,如果我理解正确,我需要以某种方式具体化我的Source以获得Flow.Publisher But I want it to be materialized in a way that it only starts running when it is subscribed to.但我希望它以一种只有在订阅时才开始运行的方式实现。

I've also tried to use toMat()我也试过使用toMat()

return Source
                .fromIterator(() -> new LivePacketIterator(maximumPacketSize))
                .filter(OrderSnapshotPacket::isNotEmpty)
                .async(dbDispatcher)
                .toMat(JavaFlowSupport.Sink.asPublisher(AsPublisher.WITHOUT_FANOUT), Keep.right())
                .???;

But I'm not sure what to do with the resulting RunnableGraph .但我不确定如何处理生成的RunnableGraph

Am I understanding this correctly?我理解正确吗? Is there a way to do what I'm trying to do?有没有办法做我想做的事?

Unfortunately, this seems to immediately start getting elements from my LivePacketIterator, even when no subscribers ahve subscribed to the returned Flow.Publisher.不幸的是,这似乎立即开始从我的 LivePacketIterator 获取元素,即使没有订阅者订阅返回的 Flow.Publisher。

What exactly do you observe to state this?你到底对state这个观察到了什么? I used a very similar snippet to yours:我使用了一个与你的非常相似的片段:

Flow.Publisher<Integer> integerPublisher =
      Source.from(List.of(1,2,3,4,5))
            .wireTap(System.out::println)
            .async()
            .runWith(
              JavaFlowSupport.Sink.asPublisher(AsPublisher.WITHOUT_FANOUT),
              ActorSystem.create());

This will not start emitting items from the list until the publisher is subscribed to.在订阅发布者之前,这不会开始从列表中发出项目。

I understand that a Source is just a sort of a template for a Subscribable source of objects (my understanding is that it's like a Factory of Publishers), and that it only converts to a concrete active source once it's materialized我知道源只是对象的可订阅源的一种模板(我的理解是它就像一个出版商工厂),并且它只有在具体化后才会转换为具体的活动源

Kind of.有点儿。 All Flow.* interfaces are part of reactive streams specification for JVM. Akka Streams treats those interfaces as SPI and doesn't use them directly in its API. It introduces its own abstractions like Source , Flow and Sink .所有Flow.*接口都是 JVM 的反应流规范的一部分。Akka Streams 将这些接口视为 SPI,并不直接在其 API 中使用它们。它引入了自己的抽象,如SourceFlowSink Akka Streams allows you to convert the processing stream expressed in its API to the lower level Flow.* just as you did in your snippet. Akka Streams 允许您将其 API 中表示的处理 stream 转换为较低级别的 Flow.*,就像您在代码段中所做的那样。 This is useful if you say want to plugin Akka Streams processing pipeline to some other reactive streams implementation like say RxJava or Project Reactor .如果您说想要将 Akka 流处理管道插入到一些其他反应流实现(例如RxJavaProject Reactor ),这将很有用。 So Source is Akka Stream's abstraction that is somehow equivalent to Flow.Publisher , that is, it's a source of potentially infinite number of values.所以Source是 Akka Stream 的抽象,在某种程度上等同于Flow.Publisher ,也就是说,它可能是无限数量的值的来源。 You need to connect Source to a Sink (potentially via a Flow ) so that you get a RunnableGraph which you can run .您需要将Source连接到Sink (可能通过Flow ),以便获得可以运行RunnableGraph This will set everything in motion and in most cases it will cause chain of subscriptions and elements will start flowing through the stream. But that is not the only option in case of JavaFlowSupport.Sink.asPublisher Sink , running the RunnableGraph will convert the whole Akka Stream to an instance of Flow.Publisher .这将使一切开始运转,在大多数情况下,它会导致订阅链,元素将开始流经 stream。但这不是JavaFlowSupport.Sink.asPublisher Sink的唯一选择,运行RunnableGraph将转换整个 Akka Stream 到Flow.Publisher的实例。 The semantics here is that the subscription is deferred until something somewhere calls subscribe on that instance.这里的语义是订阅被推迟,直到某个地方调用subscribe该实例。 Which is exactly what you're trying to achieve if I understand correctly.如果我理解正确的话,这正是您想要实现的目标。

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

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