Реактор Spring Mongodb хранилище объединяет несколько результатов вместе - PullRequest
0 голосов
/ 10 марта 2020

Я новичок в реактивном программировании и сейчас работаю над весенним приложением, основанным на webflux. Я застрял между несколькими вопросами.

public class FooServiceImpl {

@Autowired
private FooDao fooDao;

@Autowired
private AService aService;

@Autowired
private BService bService;

public long calculateSomething(long fooId) {
    Foo foo = fooDao.findById(fooId); // Blocking call one

    if (foo == null) {
        foo = new Foo();
    }

    Long bCount = bService.getCountBByFooId(fooId); // Blocking call two
    AEntity aEntity = aService.getAByFooId(fooId);  // Blocking call three

    // Do some calculation using foo, bCount and aEntity
    // ...
    // ...

    return someResult;
}
}

Так мы пишем код блокировки, который использует три результата вызова внешнего API (давайте рассмотрим вызовы БД). Я изо всех сил пытаюсь преобразовать это в реактивный код. Если все три станут моно, и если я подпишусь на все три, будет ли заблокирован внешний подписчик?

public Mono<Long> calculateSomething(long fooId) {
    return Mono.create(sink -> {
        Mono<Foo> monoFoo = fooDao.findById(fooId); // Reactive call one
        monoFoo.subscribe(foo -> {
            if (foo == null) {
                foo = new Foo();
            }

            Mono<Long> monoCount = bService.getCountBByFooId(fooId);  // Reactive call two

            monoCount.subscribe(aLong -> {
                Mono<AEntity> monoA = aService.getAByFooId(fooId);  // Reactive call three
                monoA.subscribe(aEntity -> {
                    //...
                    //...
                    sink.success(someResult);
                });
            });
        });
    };
  }

Я видел, что есть функция с именем zip, но она работает только с двумя результатами, так есть ли способ применить его здесь?

И что произойдет, если мы получим подписку на что-то внутри метода create, заблокирует ли он поток?

Будет очень благодарен, если вы могли бы помочь мне.

1 Ответ

1 голос
/ 11 марта 2020

Если бы вы дали мне расчет, который вы хотите сделать с этими значениями, мне было бы проще показать реактор, как это сделать. Но давайте предположим, что вы хотите прочитать значение из базы данных, а затем использовать это значение для другой вещи. Используйте flatmaps и создайте уникальный Flux, уменьшающий количество строк кода и сложность, не нужно использовать подписку (), как говорили другие люди. Пример:

return fooDao.findById(fooId)
.flatmap(foo -> bService.getCountBByFooId(foo))
.flatmap(bCount -> aService.getAByFooId(fooId).getCount()+bCount);
...