Как избежать чтения тела дважды в Spring Webflux? - PullRequest
0 голосов
/ 19 мая 2019

У меня есть объект MultiMeasurement в теле с одним состоянием и измерениями от 1 до n.

Мне нужно сохранить состояние и измерения в репозиториях, отправить с ними события и вернуть правильный ответот конечной точки.

fun save(multiMeasurement: Mono<MultiMeasurement>) =
    multiMeasurement.map(MultiMeasurement::validate)
        .flatMapMany { measurementCollector.save(it) }
        .doOnNext { eventSender.sendEvent(it.toMeasurementItem()) }
        .then(statusFacade.save(multiMeasurement))
        .doOnNext { eventSender.sendEvent(it.toStatusUpdateItem()) }
        .flatMap { toSettings(it.deviceId) }

Проблема со следующим кодом заключается в том, что тело читается дважды - сначала в операторе map, а затем внутри then.

Оба - statusFacade иmeasurementCollector сохранять объекты реактивным способом (монго) и возвращать соответствующие Mono s.

Результат onOperatorDebug:

|_  Mono.flatMap ⇢ com.openbrewery.beerbob.status.StatusCollector.save(StatusCollector.kt:15)
|_  Flux.then ⇢ com.openbrewery.beerbob.measurement.MeasurementFacade.save(MeasurementFacade.kt:21)
|_  Mono.doOnNext ⇢ com.openbrewery.beerbob.measurement.MeasurementFacade.save(MeasurementFacade.kt:22)
|_  Mono.flatMap ⇢ com.openbrewery.beerbob.measurement.MeasurementFacade.save(MeasurementFacade.kt:23)

Есть ли способ прочитать тело один раз и повторно-используйте его в measurementCollector и statusFacade?

1 Ответ

0 голосов
/ 20 мая 2019

Вы можете попробовать flatMap моноизмерение, оно прочитает тело один раз. Внутри flatMap остальная часть вашего кода должна быть очень похожа. Это должно быть примерно так:

fun save(multiMeasurement: Mono<MultiMeasurement>) = multiMeasurement
    .flatMap { mm ->
        measurementCollector
            .save(mm.validate())
            .doOnNext { eventSender.sendEvent(it.toMeasurementItem()) }
            .then(statusFacade.save(mm))
            .doOnNext { eventSender.sendEvent(it.toStatusUpdateItem()) }
            .flatMap { toSettings(it.deviceId) }
    }

В вашем коде multiMeasurement mono подписывается дважды, поэтому вы читаете тело дважды. Чтобы избежать этого, вам нужно вывести значение из моно один раз, а затем передать фактическое значение вперед.

...