Java 依赖关系图的反应式执行

Java 依赖关系图的反应式执行,java,graph,reactive-programming,Java,Graph,Reactive Programming,我需要创建一个服务(使用Java)来接受任务图并并行执行它们,同时考虑这些任务之间的依赖关系 例如,让我们做6项任务:A、B、C、D、E、F 依赖项包括: A->C B->C,D C->F D->E E->F 这将创建(可能的)并行执行组:A+B、C+D、E、F 如果任务执行不成功(返回错误),将不会执行其从属任务 另一个要求是对任务执行(或失败)产生副作用:通知其他服务(这意味着我们必须将失败任务的依赖关系也视为失败?) 当处理完所有任务(直接成功或失败+依赖项失败)后,我想将此“批处理”标记

我需要创建一个服务(使用Java)来接受任务图并并行执行它们,同时考虑这些任务之间的依赖关系

例如,让我们做6项任务:A、B、C、D、E、F

依赖项包括:

A->C

B->C,D

C->F

D->E

E->F

这将创建(可能的)并行执行组:A+B、C+D、E、F

如果任务执行不成功(返回错误),将不会执行其从属任务

另一个要求是对任务执行(或失败)产生副作用:通知其他服务(这意味着我们必须将失败任务的依赖关系也视为失败?)

当处理完所有任务(直接成功或失败+依赖项失败)后,我想将此“批处理”标记为已完成(调用另一个服务)

我考虑采用反应式方法解决这个问题,并使用RxJava,因为它是异步的

我对这种方法非常陌生,虽然zip/switchMap与doOnComplete/doOnError相结合似乎是一个好的方向,但我不太确定如何在这种情况下使用它们


我很高兴在这里得到一些建议:)

对于您关于根据依赖关系图(严格地说是依赖非循环图)运行观测值的查询,您可以使用and运算符组合观测值,以便根据给定图(DAG)运行

以下是根据您的示例,如何构造可观测DAG以并行执行它们:

package rxtest;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.schedulers.Schedulers;


public class ReactiveDagTest {
    private static final Logger logger = LoggerFactory.getLogger(ReactiveDagTest.class);
    private static Executor customExecutor = Executors.newFixedThreadPool(20);

    @Test
    public void stackOverflowTest() {
        Observable<Character> a = createObservable('A', 100);
        Observable<Character> b = createObservable('B', 150);
        Observable<Character> c = createObservable('C', 500);
        Observable<Character> d = createObservable('D', 200);
        Observable<Character> e = createObservable('E', 300);
        Observable<Character> f = createObservable('F', 400);

        logger.info("BEGIN");

        // As Observable for B is referred at two places in the graph, it needs to be cached to not to execute twice
        Observable<Character> bCached = b.cache();

        Observable.concat(
                Observable.merge(
                        Observable.concat(
                                Observable.merge(a, bCached),
                                c),
                        Observable.concat(bCached, d, e)),
                f)
                .toBlocking()
                .subscribe(i -> logger.info("Executed : " + i));

        logger.info("END");
    }

    private Observable<Character> createObservable(char c, int sleepMs) {
        Observable<Character> single = Observable.just(c)
                .flatMap(i -> Observable.<Character> create(s -> {
                    logger.info("onSubscribe Start Executing : {}", i);
                    sleep(sleepMs);
                    s.onNext(Character.valueOf(i));
                    s.onCompleted();
                }).subscribeOn(Schedulers.from(customExecutor)));
        return single;
    }

    private void sleep(int ms) {
        try {
            Thread.sleep(ms);
        }
        catch (InterruptedException e) {
        }
    }
}
如果任务执行不成功(返回错误),将不会执行其从属任务

这在上述解决方案中是隐含的,如果图中的任何节点失败,那么图中的其他节点将不会执行

22:19:22.107 [main] INFO rxtest.ReactiveDagTest BEGIN
22:19:22.181 [pool-1-thread-1] INFO rxtest.ReactiveDagTest onSubscribe Start Executing : A
22:19:22.181 [pool-1-thread-2] INFO rxtest.ReactiveDagTest onSubscribe Start Executing : B
22:19:22.284 [main] INFO rxtest.ReactiveDagTest Executed : A
22:19:22.333 [main] INFO rxtest.ReactiveDagTest Executed : B
22:19:22.333 [main] INFO rxtest.ReactiveDagTest Executed : B
22:19:22.333 [pool-1-thread-3] INFO rxtest.ReactiveDagTest onSubscribe Start Executing : C
22:19:22.334 [pool-1-thread-4] INFO rxtest.ReactiveDagTest onSubscribe Start Executing : D
22:19:22.534 [main] INFO rxtest.ReactiveDagTest Executed : D
22:19:22.534 [pool-1-thread-5] INFO rxtest.ReactiveDagTest onSubscribe Start Executing : E
22:19:22.833 [main] INFO rxtest.ReactiveDagTest Executed : C
22:19:22.835 [main] INFO rxtest.ReactiveDagTest Executed : E
22:19:22.835 [pool-1-thread-6] INFO rxtest.ReactiveDagTest onSubscribe Start Executing : F
22:19:23.236 [main] INFO rxtest.ReactiveDagTest Executed : F
22:19:23.236 [main] INFO rxtest.ReactiveDagTest END