All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 _) 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 _) 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