问题
I understand this kind of breaks the idea of using project-reactor
involving switching, but I am wondering if there is an appropriate way to handling this routing scenario given. Major Edit: I just went ahead and tried a more presentable implementation of the concept. Is there a significant issue with the given implementation?
public interface MonoPipe<I> {
public Mono<I> process(Mono<I> mono);
}
public static <I,P extends MonoPipe<I>> Mono<I> append(Mono<I> init, Collection<P> monoPipes){
Mono<I> output = init;
for(P pipe : monoPipes){ output = output.transform(pipe::process); }
return output;
}
public static <I,P extends MonoPipe<I>> Mono<I> appendInOrder(Mono<I> init, Collection<P> monoPipes, Comparator<P> pipeOrderer){
PriorityQueue<P> pipeQueue = new PriorityQueue<>(pipeOrderer);
pipeQueue.addAll(monoPipes);
return append(init, pipeQueue);
}
public static <I,P extends MonoPipe<I>> Mono<I> appendWithCondition(Mono<I> init, Collection<P> monoPipes, BiPredicate<P,I> condition){
return append(init, monoPipes.stream()
.map( pipe -> new ConditionalPipeWrapper(pipe,condition) )
.collect(Collectors.toList()));
}
public static <I,P extends MonoPipe<I>> Mono<I> appendWithConditionInOrder(Mono<I> init, Collection<P> monoPipes, BiPredicate<P,I> condition, Comparator<P> pipeOrderer){
return appendInOrder(init,
monoPipes.stream()
.map( pipe -> new ConditionalPipeWrapper(pipe,condition) )
.collect(Collectors.toList()),
Comparator.comparing(wrapper -> (P)wrapper.getPipe(), pipeOrderer)
);
}
public static <I,P extends MonoPipe<I>> Mono<I> route(Mono<I> init, Collection<P> monoPipes, BiPredicate<P,I> condition, P defaultPipe ){
return init.map( input -> {
P routePipe = monoPipes.stream().filter(pipe -> condition.test(pipe,input)).findFirst().orElse(defaultPipe);
return new PipeCallWrapper(input, routePipe);
}).flatMap(PipeCallWrapper::handle);
}
@Getter
@RequiredArgsConstructor
private static final class ConditionalPipeWrapper<I> implements MonoPipe<I>{
private final MonoPipe<I> pipe;
@Getter(AccessLevel.NONE)
private final BiPredicate<I,MonoPipe<I>> pipeCondition;
@Override
public Mono<I> process(Mono<I> mono) {
return mono.filter(input -> this.pipeCondition.test(input,this.pipe)).transform(this.pipe::process).switchIfEmpty(mono);
}
}
@RequiredArgsConstructor
private static class PipeCallWrapper<I>{
private final I input;
private final MonoPipe<I> pipe;
Mono<I> handle(){
return this.pipe.process(Mono.just(this.input));
}
}
来源:https://stackoverflow.com/questions/63334922/routing-transforming-a-mono-based-on-content