使用Reactive Mongo和Web客户端的非阻塞功能方法

时间:2019-01-21 01:38:12

标签: mongodb spring-data-mongodb spring-webflux

我有一个微服务,该服务使用ReactiveMongoRepository接口从数据库读取对象。

目标是获取这些对象中的每个对象并将其推送到AWS Lambda函数(将其转换为DTO之后)。如果该lambda函数的结果在200范围内,则将该对象标记为成功,否则将其忽略。

在过去的简单Mongo存储库和RestTemplate中,这是一件微不足道的任务。但是,我试图理解此无功交易,并避免阻塞。

这是我想出的代码,我知道我在webClient上受阻,但是如何避免呢?

@Override
public Flux<Video> index() {
    return videoRepository.findAllByIndexedIsFalse().flatMap(video -> {
        final SearchDTO searchDTO = SearchDTO.builder()
                .name(video.getName())
                .canonicalPath(video.getCanonicalPath())
                .objectID(video.getObjectID())
                .userId(video.getUserId())
                .build();

        // Blocking call
        final HttpStatus httpStatus = webClient.post()
                .uri(URI.create(LAMBDA_ENDPOINT))
                .body(BodyInserters.fromObject(searchDTO)).exchange()
                .block()
                .statusCode();

        if (httpStatus.is2xxSuccessful()) {
            video.setIndexed(true);
        }

        return videoRepository.save(video);
    });
}

我是从计划任务中调用上述代码的,而我实际上并不关心index()方法的实际结果,而只是在执行期间会发生什么。

@Scheduled(fixedDelay = 60000)
public void indexTask() {
    indexService
            .index()
            .log()
            .subscribe();
}

我已经阅读了很多有关该主题的博客文章,但它们只是简单的CRUD操作,中间没有发生任何事情,因此请不要真正给我提供有关如何实现这些内容的完整信息。

有帮助吗?

2 个答案:

答案 0 :(得分:1)

您的解决方案实际上非常接近。 在这种情况下,您应该逐步分解反应链,而为了清晰起见,请毫不犹豫地将位转换为独立的方法。

@Override
public Flux<Video> index() {

    Flux<Video> unindexedVideos = videoRepository.findAllByIndexedIsFalse();
    return unindexedVideos.flatMap(video -> {
        final SearchDTO searchDTO = SearchDTO.builder()
                .name(video.getName())
                .canonicalPath(video.getCanonicalPath())
                .objectID(video.getObjectID())
                .userId(video.getUserId())
                .build();

        Mono<ClientResponse> indexedResponse = webClient.post()
            .uri(URI.create(LAMBDA_ENDPOINT))
            .body(BodyInserters.fromObject(searchDTO)).exchange()
            .filter(res -> res.statusCode().is2xxSuccessful());

        return indexedResponse.flatMap(response -> {
            video.setIndexed(true);
            return videoRepository.save(video);
        });
    });

答案 1 :(得分:0)

我的方法,可能更具可读性。但是我承认我没有运行它,所以不能100%保证它会运行。

public Flux<Video> index() {
    return videoRepository.findAll()
        .flatMap(this::callLambda)
        .flatMap(videoRepository::save);
}

private Mono<Video> callLambda(final Video video) {
    SearchDTO searchDTO = new SearchDTO(video);
    return webClient.post()
            .uri(URI.create(LAMBDA_ENDPOINT))
            .body(BodyInserters.fromObject(searchDTO))
            .exchange()
            .map(ClientResponse::statusCode)
            .filter(HttpStatus::is2xxSuccessful)
            .map(t -> {
                video.setIndexed(true);
                return video;
            });
}