简体   繁体   English

如何在准备就绪时使用反应式 Flux/Mono 将消息推送到上游而不是在间隔中轮询状态?

[英]How to push message to upstream using reactive Flux/Mono whenever they are ready than polling in interval for status?

Trying to push message to upstream whenever they are available/ready and close connection after flush, rather than polling for message using spring reactive flux interval.尝试在消息可用/准备好并在刷新后关闭连接时将消息推送到上游,而不是使用 spring 反应通量间隔轮询消息。

@GetMapping(value = "/getValue/{randomId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> statusCheck(@PathVariable("randomId") @NonNull String randomId) {

return Flux.<String>interval(Duration.ofSeconds(3))
                .map(status -> {
                    if (getSomething(randomId).
                            equalsIgnoreCase("value"))
                        return "value";
                    return "ping";
                }).take(Duration.ofSeconds(60)).timeout(Duration.ofSeconds(60));
    }

Kafka listener updates randomId value in a map as it gets, getSomething method checks for randomId value in intervals in map. Kafka 侦听器在获取时更新地图中的 randomId 值,getSomething 方法检查地图中间隔的 randomId 值。 So instead of checking in intervals and storing data in map, i want to push message to client when listener receives.因此,我想在侦听器接收到消息时将消息推送到客户端,而不是检查间隔并将数据存储在地图中。

This sounds like a Flux.create() request:这听起来像是一个Flux.create()请求:

return Flux.<String>create(emitter -> {
     if (getSomething(randomId).equalsIgnoreCase("value")) {
          sink.next("value");
     }
     else {
          sink.next("ping");
     }
  });

/**
 * Programmatically create a {@link Flux} with the capability of emitting multiple
 * elements in a synchronous or asynchronous manner through the {@link FluxSink} API.
 * This includes emitting elements from multiple threads.
 * <p>
 * <img class="marble" src="doc-files/marbles/createForFlux.svg" alt="">
 * <p>
 * This Flux factory is useful if one wants to adapt some other multi-valued async API
 * and not worry about cancellation and backpressure (which is handled by buffering
 * all signals if the downstream can't keep up).
 * <p>
 * For example:
 *
 * <pre><code>
 * Flux.&lt;String&gt;create(emitter -&gt; {
 *
 *     ActionListener al = e -&gt; {
 *         emitter.next(textField.getText());
 *     };
 *     // without cleanup support:
 *
 *     button.addActionListener(al);
 *
 *     // with cleanup support:
 *
 *     button.addActionListener(al);
 *     emitter.onDispose(() -> {
 *         button.removeListener(al);
 *     });
 * });
 * </code></pre>
 *
 * @reactor.discard The {@link FluxSink} exposed by this operator buffers in case of
 * overflow. The buffer is discarded when the main sequence is cancelled.
 *
 * @param <T> The type of values in the sequence
 * @param emitter Consume the {@link FluxSink} provided per-subscriber by Reactor to generate signals.
 * @return a {@link Flux}
 * @see #push(Consumer)
 */
public static <T> Flux<T> create(Consumer<? super FluxSink<T>> emitter) {

I built solution based on this stackoverflow Spring 5 Web Reactive - Hot Publishing - How to use EmitterProcessor to bridge a MessageListener to an event stream answer, used EmitterProcessor to hot publish message as they are available.我基于此 stackoverflow Spring 5 Web Reactive - Hot Publishing - How to use EmitterProcessor 将 MessageListener 桥接到事件流答案构建了解决方案,使用 EmitterProcessor 在消息可用时对其进行热发布。

Here is the sample code这是示例代码

@GetMapping(value = "/getValue/{randomId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> statusCheck(@PathVariable("randomId") @NonNull String randomId) {
    EmitterProcessor<String> emitterProcessor = EmitterProcessor.create();
    Flux<String> autoConnect = emitterProcessor.publish().autoConnect();
    FluxSink<String> sink = emitterProcessor.sink();
    //storing randomId and processor sink details
    randomIdMap.putIfAbsent(randomId, emitterProcessor);
    /** This will return ping status to notify client as 
    connection is alive until the randomId message received. **/
    sendPingStatus(sink, randomId);
}

Below method shows how to pushes message to client as it arrives on kafka consumer and close flux connection.下面的方法显示了如何在消息到达 kafka 消费者并关闭通量连接时将消息推送到客户端。

@KafkaListener(topics = "some-subscription-id",
        containerFactory = "kafkaListenerContainerFactory")
public void pushMessage(SomeMessage message, Acknowledgment acknowledgment) {
    EmitterProcessor emitter = randomIdMap.get("randomId");
    if (emitter != null ) {
        emitter.onNext(message);
        emitter.onComplete();
        randomIdMap.remove("randomId");
        acknowledgment.acknowledge();
    }
}

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

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