Как передать данные по реактивной цепочке

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

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 а что если это не так)?

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

1 ответ

Исходя из того, что вы поделились, вы можете просто сделать следующее:

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

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

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

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

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


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

Другие вопросы по тегам