io.jaspercloud.react.mono.ReactInvokeChain Maven / Gradle / Ivy
package io.jaspercloud.react.mono;
import io.jaspercloud.react.mono.invoke.InvokeRequest;
import io.jaspercloud.react.mono.invoke.InvokeResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoSink;
import reactor.core.scheduler.Schedulers;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
public final class ReactInvokeChain {
private ReactInvokeChain() {
}
public static AsyncMono filterCall(List> monoList, FilterCallback call) {
AsyncMono asyncMono = new AsyncMono<>(Mono.create(new Consumer>() {
@Override
public void accept(MonoSink sink) {
try {
Iterator> iterator = monoList.iterator();
if (!iterator.hasNext()) {
sink.success(call.notFound());
return;
}
doNext(iterator, iterator.next(), sink, call);
} catch (Throwable e) {
sink.error(e);
}
}
}));
return asyncMono;
}
public static AsyncMono mergeCall(List> monoList, MergeCallback callback) {
Mono mono = Mono.create(new Consumer>() {
@Override
public void accept(MonoSink sink) {
List> resultList = new CopyOnWriteArrayList<>();
if (monoList.isEmpty()) {
sink.success(callback.process(resultList));
return;
}
monoList.forEach(e -> {
K key = e.getKey();
e.getRoute().subscribeOn(Schedulers.parallel()).then(new ReactAsyncCall() {
@Override
public void process(boolean hasError, Throwable throwable, T result, ReactSink super Void> _) throws Throwable {
try {
if (hasError) {
resultList.add(new InvokeResponse<>(key, throwable));
} else {
resultList.add(new InvokeResponse<>(key, result));
}
} finally {
if (resultList.size() == monoList.size()) {
sink.success(callback.process(resultList));
}
}
}
}).subscribe();
});
}
});
return new AsyncMono<>(mono);
}
private static void doNext(Iterator> iterator,
InvokeRequest mono, MonoSink sink,
FilterCallback call) {
K key = mono.getKey();
AsyncMono asyncMono = mono.getRoute();
asyncMono.subscribeOn(Schedulers.parallel()).then(new ReactAsyncCall() {
@Override
public void process(boolean hasError, Throwable throwable, T result, ReactSink super O> _) throws Throwable {
try {
ResponseEntity entity = call.process(key, hasError, throwable, result);
if (HttpStatus.OK.value() != entity.getStatusCodeValue()) {
if (iterator.hasNext()) {
doNext(iterator, iterator.next(), sink, call);
} else {
sink.success(call.notFound());
}
} else {
sink.success(entity.getBody());
}
} catch (Throwable ex) {
sink.error(ex);
}
}
}).subscribe();
}
public interface FilterCallback {
ResponseEntity process(K key, boolean hasError, Throwable throwable, I result);
default O notFound() {
return null;
}
}
public interface MergeCallback {
O process(List> list);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy