Java 如何不依赖于反应器中的订阅时间
我已经阅读了整个反应堆的文档,但是我无法找到以下问题的正确模式。 我有一个方法,应该异步地做一些事情。我以流量的形式返回结果响应,消费者可以订阅它 该方法具有以下定义:Java 如何不依赖于反应器中的订阅时间,java,reactive-programming,project-reactor,Java,Reactive Programming,Project Reactor,我已经阅读了整个反应堆的文档,但是我无法找到以下问题的正确模式。 我有一个方法,应该异步地做一些事情。我以流量的形式返回结果响应,消费者可以订阅它 该方法具有以下定义: Flux<ResultMessage> sendRequest(RequestMessage message); 实现可以如下所示: Flux<ResultMessage> sendRequest(RequestMessage message) { Flux<ResultMessage>
Flux<ResultMessage> sendRequest(RequestMessage message);
实现可以如下所示:
Flux<ResultMessage> sendRequest(RequestMessage message) {
Flux<ResultMessage> result = incomingMessageStream
.filter( resultMessage -> Objects.equals( resultMessage.getId(), message.getId() ) )
.take( 2 );
// The message sending is done here...
return result;
}
通量发送请求(请求消息){
流量结果=输入消息流
.filter(resultMessage->Objects.equals(resultMessage.getId(),message.getId())
.采取(2);
//消息发送在此处完成。。。
返回结果;
}
其中,incomingMessageStream
是通过此通道的所有消息的流量。
这个实现的问题是,消费者在结果消息发出后被订阅,它可能会错过其中一些消息
所以,我正在寻找一个解决方案,让消费者不依赖于订阅时间。潜在消费者可能根本不需要订阅产生的
Flux
。我正在寻找一个通用的解决方案,但如果不可能,您可以假定生成的消息数不超过2。一段时间后,我创建了一个似乎有效的解决方案:
Flux<ResultMessage> sendRequest(RequestMessage message) {
final int maxResponsesCount = 2;
final Duration responseTimeout = Duration.ofSeconds( 10 );
final Duration subscriptionTimeout = Duration.ofSeconds( 5 );
// (1)
ConnectableFlux<ResultMessage> result = incomingMessageStream
.ofType( ResultMessage.class )
.filter( resultMessage ->Objects.equals(resultMessage.getId(), message.getId() ) )
.take( maxResponsesCount )
.timeout( responseTimeout )
.replay( maxResponsesCount );
Disposable connectionDisposable = result.connect();
// (2)
AtomicReference<Subscription> subscriptionForCancelSubscription = new AtomicReference<>();
Mono.delay( subscriptionTimeout )
.doOnSubscribe( subscriptionForCancelSubscription::set )
.subscribe( x -> connectionDisposable.dispose() );
// The message sending is done here...
// (3)
return result
.doOnSubscribe(s ->subscriptionForCancelSubscription.get().cancel())
.doFinally( signalType -> connectionDisposable.dispose() );
}
通量发送请求(请求消息){
最终整数MaxResponseCount=2;
最终持续时间响应超时=持续时间秒(10);
最终持续时间subscriptionTimeout=持续时间秒(5);
// (1)
ConnectableFlux结果=incomingMessageStream
.of类型(ResultMessage.class)
.filter(resultMessage->Objects.equals(resultMessage.getId(),message.getId())
.take(最大响应计数)
.超时(响应超时)
.重播(最大响应计数);
一次性连接Disposable=result.connect();
// (2)
AtomicReference subscriptionForCancelSubscription=新的AtomicReference();
单声道延迟(subscriptionTimeout)
.DoonSubscripte(订阅ForCancelSubscription::set)
.subscribe(x->connectionDisposable.dispose());
//消息发送在此处完成。。。
// (3)
返回结果
.doonSubscripte(s->subscriptionForCancelSubscription.get().cancel())
.doFinally(signalType->connectionDisposable.dispose());
}
我使用的ConnectableFlux可以立即连接到流,而无需订阅,它被设置为使用reply()方法来存储所有消息,这样以后任何订阅方都不会错过响应消息(1)
可以执行的路径很少:
- 解决方案-如果未完成订阅,则有一个计时器可在5秒后删除连接的流量资源。(二)
- 解决方案-设置了获取响应的超时(
)。然后,.timeout(responseTimeout)
清理资源(1)(3).doFinally(…)
- 解决方案-与2.1相同
- 解决方案-执行
是因为达到了最大元素数(doFinally()
)(1)(3).take(maxresponsecount)
Flux<ResultMessage> sendRequest(RequestMessage message) {
final int maxResponsesCount = 2;
final Duration responseTimeout = Duration.ofSeconds( 10 );
final Duration subscriptionTimeout = Duration.ofSeconds( 5 );
// (1)
ConnectableFlux<ResultMessage> result = incomingMessageStream
.ofType( ResultMessage.class )
.filter( resultMessage ->Objects.equals(resultMessage.getId(), message.getId() ) )
.take( maxResponsesCount )
.timeout( responseTimeout )
.replay( maxResponsesCount );
Disposable connectionDisposable = result.connect();
// (2)
AtomicReference<Subscription> subscriptionForCancelSubscription = new AtomicReference<>();
Mono.delay( subscriptionTimeout )
.doOnSubscribe( subscriptionForCancelSubscription::set )
.subscribe( x -> connectionDisposable.dispose() );
// The message sending is done here...
// (3)
return result
.doOnSubscribe(s ->subscriptionForCancelSubscription.get().cancel())
.doFinally( signalType -> connectionDisposable.dispose() );
}