Как передать данные по реактивной цепочке - PullRequest
0 голосов
/ 15 сентября 2018

Всякий раз, когда мне нужно передать данные по реактивной цепочке, я в конечном итоге делаю что-то вроде этого:

public Mono<String> doFooAndPassDtoAsMono(Dto dto) {
    return Mono.just(dto)
        .flatMap(dtoMono -> {
            Mono<String> result = // remote call returning a Mono
            return Mono.zip(Mono.just(dtoMono), result);
        })
        .flatMap(tup2 -> {
            return doSomething(tup2.getT1().getFoo(), tup2.getT2()); // do something that requires foo and result and returns a Mono
        });
}

Учитывая приведенный ниже примерный класс Dto:

class Dto {
    private String foo;

    public String getFoo() {
        return this.foo;
    }
}

Потому что это частоУтомительно все время архивировать данные, чтобы передать их по цепочке (особенно на несколько уровней вниз). Мне было интересно, можно ли просто ссылаться на dto прямо так:

public Mono<String> doFooAndReferenceParam(Dto dto) {
       Mono<String> result = // remote call returning a Mono
        return result.flatMap(result -> {
            return doSomething(dto.getFoo(), result); // do something that requires foo and result and returns a Mono
        });
}

Моя обеспокоенность по поводуВторой подход заключается в том, что, если подписчик подписывается на этот Mono в пуле потоков, мне нужно будет гарантировать, что Dto является потокобезопасным (приведенный выше пример прост, потому что он просто несет String, но что, если это не так)?

Кроме того, какой из них считается "наилучшей практикой"?

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

Дело простое, если

  • Справочные данные доступны с самого начала (т.е. до создания цепочки), а
  • Цепочка создана для обработки не более одного события (т. Е. Начинается с Mono) и
  • Справочные данные неизменны.

Тогда вы можете просто ссылаться на справочные данные в параметре или локальной переменной - как в вашем втором решении. Это совершенно нормально, и нет проблем с параллелизмом.


Использование изменяемых данных в реактивных потоках настоятельно не рекомендуется. Если у вас был изменяемый класс Dto, вы все равно сможете его использовать (при условии правильной синхронизации), но это будет очень удивительно для читателей вашего кода.

0 голосов
/ 15 сентября 2018

На основании того, что вы поделились, вы можете просто сделать следующее:

public Mono<String> doFooAndPassDtoAsMono(Dto dto) {
    return Mono.just(dto.getFoo());
}

То, как вы используете zip в первом варианте, не решает никаких задач. Аналогично, 2-й вариант также не будет работать, поскольку, если моно пусто, следующая плоская карта не будет запущена.

...