Reactor Flux - 仅在完成时从发布者发出

问题描述

我有一些 Reactor Kafka 代码,它通过 KafkaReceiver 读入事件,并通过 1 个或多个 KafkaSenders 写入 1..许多下游消息,这些消息连接成单个 Publisher。一切都很好,但我想要做的只是在它完成时从这个连接的发件人 Flux 发出一个事件(即它已完成写入任何给定事件的所有下游主题,因此它不会发出每个元素的任何内容,因为它在下游写入 Kafka 直到完成)。通过这种方式,我可以 sample() 并定期提交偏移量,知道每当 sample() 碰巧触发并且我为传入事件提交偏移量,我已经处理了每个事件的所有下游消息提交偏移量。似乎我可以以某种方式使用 pauseUntilOther()then(),但我不太清楚如何给定我的代码和特定用例。感谢任何想法或建议,谢谢。

主要发布者代码

this.kafkaReceiver.receive()
        .groupBy(m -> m.receiverOffset().topicPartition())
        .flatMap(partitionFlux ->
                partitionFlux.publishOn(this.scheduler)
                        .flatMap(this::processEvent)
                        .sample(Duration.ofMillis(10))
                        .concatMap(sr -> commitReceiverOffset(sr.correlationMetadata())))
        .subscribe();

通过调用 processEvent() 返回的串联 KafkaSenders:

return Flux.concat(kafkaSenderFluxA,kafkaSenderFluxB)
        .doOnComplete(LOG.info(“Finished writing all downstream messages for incoming event);

解决方法

听起来像 Flux.last() 是您要找的:

return Flux.concat(kafkaSenderFluxA,kafkaSenderFluxB)
    .doOnComplete(LOG.info(“Finished writing all downstream messages for incoming event)
    .last();

然后,您的 .sample(Duration.ofMillis(10)) 会做任何可以作为发送给这些经纪人的一批或几批中的最后一项的任何事情。最后,您的 commitReceiverOffset() 将正确提交最后一个。

有关详细信息,请参阅其 JavaDoc:

/**
 * Emit the last element observed before complete signal as a {@link Mono},or emit
 * {@link NoSuchElementException} error if the source was empty.
 * For a passive version use {@link #takeLast(int)}
 *
 * <p>
 * <img class="marble" src="doc-files/marbles/last.svg" alt="">
 *
 * <p><strong>Discard Support:</strong> This operator discards elements before the last.
 *
 * @return a {@link Mono} with the last value in this {@link Flux}
 */
public final Mono<T> last() {

和大理石图:https://projectreactor.io/docs/core/release/api/reactor/core/publisher/doc-files/marbles/last.svg