Reputation: 51
I have a webflux application. In one place I make 3 API calls. Every call depends on result of previous call.
Mono<List<Book>> books = bookService.find(params); //1st API call
Mono<List<User>> users = books.flatMapMany(Flux::fromIterable)
.map(User::getId)
.collectList()
.map(allUserIds -> userService.findUsers(allUserIds)) //2nd API call
.flatMap(mono -> mono);
Mono<List<User>> parents = users.flatMapMany(Flux::fromIterable)
.filter(user -> user.getParentId() != null)
.map(User::getParentId)
.collectList()
.map(parentIds -> userService.findUsers(parentIds)) //3rd API call
.flatMap(mono -> mono);
Mono<List<User>> usersWithParents = Flux.merge(users, parents)
.flatMapIterable(Function.identity())
.collectList();
This code works, but I get 4 API calls in total. I get two API calls for 2nd step. I assume that reactor makes 1 call to calculate parents variable and 2n call for Flux.merge(users, parents). How can I update the call to avoid extra API call?
Upvotes: 0
Views: 1313
Reputation: 19484
I think you should do smth like this
public Mono<List<User>> getAllUsers(){
Mono<List<String>> booksMono = bookService.find(params)
.flatMapMany(Flux::fromIterable)
.map(User::getId)
.flatMap(book->userService.findUsers(allUserIds))
.collectList()
.flatMap(users->Mono.zip(users, getParents(users)))
.flatMap(zippedUsers-> Stream.concat(zippedUsers.getT1(), zippedUsers.getT2()));
}
private Mono<List<User>> getParents(List<User> users){
return Flux.fromIterable(users)
.filter(user -> user.getParentId() != null)
.map(User::getParentId)
.collectList()
.map(parentIds -> userService.findUsers(parentIds));
}
Upvotes: 2
Reputation: 51
Found a solution. We need to combine 2nd and 3rd API calls into one chain with flatmap:
Mono<List<Book>> books = bookService.find(params); //1st API call
Mono<List<User>> users = books.flatMapMany(Flux::fromIterable)
.map(User::getId)
.collectList()
.map(allUserIds -> userService.findUsers(allUserIds)) //2nd API call
.flatMap(mono -> mono);
.flatMap(children -> {
List<Long> parentIds = children.stream()
.filter(child -> child.getParentId() != null)
.map(User::getParentId)
.collect(toList());
return userService.findUsers(parentIds);
});
Upvotes: 0