Недавно я изучал реактивное программирование с использованием библиотек реакторов в Java со средой Spring, и по большей части мне удалось с этим справиться. Однако пару раз я оказывался в такой же ситуации и хотел бы посоветовать, где я ошибаюсь.
Суть того, с чем я борюсь, часто заключается в том, что я хочу что-то сделать с моно, например, найти некоторые дополнительные данные, а затем добавить их обратно в исходный моно. Функция zip кажется мне идеальным кандидатом, но затем я дважды подписываюсь на исходный моно, что не входит в мои намерения.
Вот надуманный пример ситуации, которую я пытался решить, поскольку не могу поделиться кодом своей компании. Предполагается, что мы используем библиотеку реактивных данных и настроили регистратор, а класс Person неизменен, но имеет методы ‹FieldName›.
public Mono<Person> getPersonWithFamilyMembers(Integer id){
log.info("Finding person with id {}", id);
personRepository.findById(id)
.switchIfEmpty(Mono.error(NotFoundException::new))
.doOnNext(person -> log.info("Found person: {}", person))
.as(this::fetchAndAddFamilyMembers)
.doOnSuccess(person -> log.info("Successfully found person with family members"));
}
private Mono<Person> fetchAndAddFamilyMembers(Mono<Person> personMono){
Mono<List<Person>> familyMembersMono = personMono
.map(Person::getFamilyId)
.flatMapMany(PersonRepository::findByFamilyId)
.collectList();
return personMono.zipWith(familyMembersMono, Person::withFamilyMembers);
}
Результат, который я вижу при запуске такого кода:
INFO | Finding person with id 1
INFO | Found person: Person(id=1, familyId=1, familyMembers=[])
INFO | Found person: Person(id=1, familyId=1, familyMembers=[])
INFO | Successfully found person with family members
Это имеет смысл, поскольку исходный моно человека был подписан в двух местах, где я сопоставляю его с familyMembersMono
, и когда я объединяю их вместе, но я не хочу делать ненужные вызовы в репозиторий, если я могу этого избежать.
Есть ли у кого-нибудь предложение, как лучше справиться с таким поведением?