Similar to How to process each product one by one with incremental progress update using Spring reactive?
The thing I want to do is given
enum Status {
PROCESSING,
ERROR,
COMPLETE
}
record MyResp {
String requestId;
Status status;
double progress;
URI result;
String errorMessage;
};
Mono<MyResp> requestSomethingSlow(MyReqObjectNotRelevant request);
/**
* Sets status to SUCCESS or return a Mono.error()
*/
Mono<MyResp> checkIfDone(String requestId);
I want a method like:
Flux<MyResp> requestSomethingSlowFlux(MyReqObjectNotRelevant request, Duration delay) {
return ...???
??? requestSomethingSlow(request)
. ???
.delayElements(delay)
. ???
. checkIfDone(...?)
...???
}
I am thinking it's something like Flux.generate
but how do I convert the Mono<MyResp>
to a Callable and use it with the generator function?
I was also looking at Mono.expand
as shown in How do I create a Flux using generate wrapping calls that return a Mono but that wouldn't work because I don't have a finite set of calls.
So far my implementation attempt looks like
Flux<MyResp> requestSomethingSlowFlux(MyReqObjectNotRelevant request, Duration delay) {
return requestSomethingSlow(request)
.flatMapMany(initialResponse -> {
if (initialResponse.getStatus() == COMPLETE) {
return Flux.just(initialResponse);
} else if (initialResponse.getStatus() == ERROR) {
return Flux.error(
new IllegalStateException(
initialResponse.getErrorMessage()));
} else {
... still figuring this part out
}
}
.delayElements(delay)
}
Also similar to How do you implement Polling Logic in Project Reactor? but I want it as a flux of events that show progress rather than all or none.
Using this answer but removing the last()
call so I get all events.
Flux<MyResp> requestSomethingSlowFlux(MyReqObjectNotRelevant request, Duration delay) {
return requestSomethingSlow(request)
.flatMapMany(initialResponse -> {
if (initialResponse.getStatus() == COMPLETE) {
return Flux.just(initialResponse);
} else if (initialResponse.getStatus() == ERROR) {
return Flux.error(
new IllegalStateException(
initialResponse.getErrorMessage()));
} else {
return checkIfDone(initialResponse.getRequestId())
.repeatWhen(repeat -> repeat.delayElements(delay))
.doNext(response -> {
if (response.getStatus() == ERROR) {
throw new IllegalStateException(
initialResponse.getErrorMessage());
}
})
.takeUntil(response -> response.getStatus() != PROCESSING)
}
});
}
It has a few flaws though
repeatWhen
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.