Routing/Transforming a Mono based on content

笑着哭i 提交于 2021-02-10 19:52:29

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!