Вставка в две коллекции без блокировки

#spring-boot #kotlin #spring-data-mongodb #spring-webflux

#весенняя загрузка #kotlin #spring-данные-mongodb #spring-webflux

Вопрос:

В настоящее время я изучаю Project Reactor с использованием Spring-WebFlux.

Я создал простой сервис, который будет последовательно вставлять в две коллекции. Во-первых, мой сервис будет вставлен в коллекцию list, а после этого он будет вставлен в коллекцию details. Если обе операции завершатся успешно, будет возвращен экземпляр первой операции (Вставить в коллекцию списков), если одна из них не завершится успешно, будет выполнен откат всех изменений, созданных предшествующей операцией.

Вот мой фрагмент:

     override fun insert(business: Business): Mono<Business> = businessRepository.save(business)
    .doOnSuccess { businezz ->
        val businessDetails = businezz.businessDetails
        businessDetails!!.idBusiness = businezz.id
        businessDetailsService.insert(businessDetails).doOnError {
            businessRepository.delete(businezz).subscribe()
        }.subscribe()
    }
  

Я чувствую, что это своего рода грязный способ создания Mono. Поскольку вторая операция является блочной операцией. Конечно, я мог бы просто вставить список, затем вставить детали, а затем получить список. Но на самом деле это будет вызывать базу данных 3 раза, а не 2 раза, как в моем коде выше.

Есть ли у меня какой-нибудь способ создать неблокирующую операцию и вызвать базу данных только 2 раза?

Спасибо.

Комментарии:

1. Привет, Дэвид, я удалил тег Java, поскольку в вашем вопросе используется только Kotlin.

2. Спасибо @LppEdd, я подумал, что, поскольку Kotlin — это просто расширение Java, будет нормально добавить тег java. В следующий раз я буду осторожен.

Ответ №1:

Я не знаком с Kotlin, но с Java вы могли бы сделать это следующим образом:

 Mono<Business> insert(Business business) {
    return businessRepository.save(business)
            .flatMap(businezz -> {
                BusinessDetails businessDetails = ...;
                return businessDetailsService.insert(businessDetails)
                        .onErrorResume(throwable -> businessRepository
                                .delete(businezz)
                                .then(Mono.empty()))
                        .then(Mono.just(businezz));
            });
}
  

ОТВЕТ KOTLIN, спасибо, Дэвид:

 override fun insert(business: Business): Mono<Business> {
    return businessRepository.save(business).flatMap { businezz ->
        val businessDetails = businezz.businessDetails
        businessDetailsService.insert(businessDetails!!).onErrorResume { 
            businessRepository.delete(businezz).then(Mono.empty())
        }.then(Mono.just(businezz))
    }        
}
  

Комментарии:

1. Спасибо @Alexander Pankin. Вы подаете мне идею. Последний вопрос, зачем использовать flatMap вместо map? Поскольку я использую Mono, а не Flux

2. В реакторе flatMap поток не «выравнивается» до Mono. Мы используем это с Mono или Flux, когда необходимо передать значение «next» другому асинхронному издателю. И мы используем map , когда передаем «следующее» значение синхронной функции.

3. Спасибо за объяснение!!