当前位置: 首页 > 知识库问答 >
问题:

带扩展的反应器延迟分页

松亦
2023-03-14

基于如何使用Spring引导WebClient收集分页API响应?

我创建了以下爬虫类

class GitlabCrawler(private val client: WebClient, private val token: String) {

    fun fetchCommits(project: URI): Flux<Commit> {
        return fetchCommitsInternal(project).expand { cr: ClientResponse? ->
                val nextUrl = getNextUrl(cr)

                nextUrl?.let { fetchCommitsInternal(URI.create(it)) }
                        ?: Mono.empty<ClientResponse>()
        }.limitRate(1)
                .flatMap { cr: ClientResponse? -> cr?.bodyToFlux(Commit::class.java) ?: Flux.empty() }


    }

    private fun getNextUrl(cr: ClientResponse?):String? {
        // TODO replace with proper link parsing
        return cr?.headers()?.header(HttpHeaders.LINK)?.firstOrNull()
                ?.splitToSequence(",")
                ?.find { it.endsWith("rel=\"next\"") }
                ?.let { it.substring(it.indexOf('<') + 1, it.lastIndexOf('>')) }
    }

    private fun fetchCommitsInternal(url: URI): Mono<ClientResponse> {
        return client.get()
                .uri(url)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .header("Private-Token", token)
                .exchange()
    }
}


data class Commit(
        val id: String,
        val message: String,
        @JsonProperty("parent_ids") val parentIds: List<String>,
        @JsonProperty("created_at") val createdAt: String)

我希望避免不必要的请求,但它执行的请求比满足请求所需的多。

gitlabCrawler.fetchCommits(URI.create("https://...")).take(15).collectList().block()

只需要一个请求,因为每个页面包含20个条目,但它会启动第二个页面请求。它似乎总是要求多出一页。我尝试使用limitRate,但似乎没有效果。

有没有一种方法可以让它变得懒惰,即只有在当前页面用完时才请求下一页?

共有1个答案

苍轶
2023-03-14

您确信它确实执行了请求吗<调用code>FetchCommitterName意味着WebFlux已“准备”请求,而不一定是已执行(即已订阅)。

用例的以下简化显示了差异:

private static Tuple2<Integer, Flux<Integer>> nextPage(int index, int pageSize) {
    System.out.println("prepared a request for page " + index);
    return Tuples.of(index, Flux.range((pageSize * (index - 1)) + 1, pageSize));
}

@Test
public void expandLimitedRequest() {
    int pageSize = 5;
    Flux.just(nextPage(1, pageSize))
        .doOnSubscribe(sub -> System.out.println("requested first page"))
        .expand(page -> {
            int currentPage = page.getT1();
            if (currentPage < 3) {
                int nextPage = currentPage + 1;
                return Flux.just(nextPage(nextPage, pageSize))
                           .doOnSubscribe(sub -> System.out.println("requested page " + nextPage));
            }
            return Flux.empty();
        })
        .doOnNext(System.out::println)
        .flatMap(Tuple2::getT2)
        .doOnNext(System.out::println)
        .take(8)
        .blockLast();
}

印刷品:

prepared a request for page 1
requested first page
[1,FluxRange]
1
2
3
4
5
prepared a request for page 2
requested page 2
[2,FluxRange]
6
7
8
prepared a request for page 3

如您所见,它准备了第3页的请求,但从未执行它(因为take下游取消了之前的expand)。

 类似资料:
  • 问题内容: 我正在尝试使用新的React Lazy和Suspense创建后备加载组件。这很好用,但后备时间仅显示几毫秒。有没有办法增加额外的延迟或最短时间,因此我可以在渲染下一个组件之前显示该组件的动画? 现在懒导入 等待组件: 我可以做这样的事情吗? 问题答案: 函数应该返回对象的承诺,该对象由具有默认导出功能的模块返回。不会返回承诺,也不能那样使用。尽管任意承诺可以: 如果目标是提供 最小的

  • 我正在制作一个待办事项列表应用程序,并有3种自定义单元格类型。对于任务单元格,它只是左侧的图像视图和右侧的文本视图。我希望单元格在文本视图文本对于单行来说太大时自动调整大小。 我已经添加了正确的约束,并将其添加到viewWillAppear中 但是,当进入带有tableview的视图时,单元格会在一秒钟内保持较小,然后扩展到正确的大小。此外,在最初添加任务时,单元格不会调整大小,除非返回并再次打开

  • 本文向大家介绍带宽延迟积,包括了带宽延迟积的使用技巧和注意事项,需要的朋友参考一下 带宽延迟乘积是多少位可以填充网络链路的度量。它给出了发送方在等待确认之前在给定时间可以传输的最大数据量。因此,这是未确认数据的最大数量。 测量 带宽延迟乘积的计算公式是通道的链路容量与传输的往返延迟时间的乘积。 通道的链路容量是每秒传输的位数。因此,其单位为bps,即每秒位数。 往返延迟时间是信号从发送方发送到接收

  • 首先,是否有人对GRPC客户机服务器实现与websocket protobuf客户机服务器实现之间的吞吐量/延迟进行了性能比较?或者至少是类似的东西。 为了实现这一目标,我正在试用示例JAVA helloworld grpc客户机服务器,并尝试将响应的延迟与类似的websocket客户机服务器进行比较。目前,我正在本地机器上用客户端和服务器进行测试。 websocket客户端服务器在服务器端有一个

  • 问题内容: 如果这是完全相同的内容,请纠正我,我知道这个话题经常被讨论,但是找不到确切的答案。 问题: 在MVC Web应用程序中处理Hibernate对象的最佳实用解决方案是什么? 细节: 我正在使用Hibernate,并希望在可能的情况下利用延迟加载。 我正在使用MVC风格的webapp。 我讨厌获得延迟加载初始化异常。 我讨厌不得不在事务之间重新连接Hibernate对象。 选项: 渴望装载

  • 主要内容:SDF 文件,实例,实例,实例关键词: 延迟反标注, SDF 延迟反标注是设计者根据单元库工艺、门级网表、版图中的电容电阻等信息,借助数字设计工具将延迟信息标注到门级网表中的过程。利用延迟反标注后的网表,就可以进行精确的时序仿真,使仿真更接近实际工作的数字电路。 延迟反标注过程 前面教程中的仿真基本都是功能性的仿真。无论是进行 IC 设计还是 FPGA 开发,时序仿真都是必不可少的。《Verilog 教程》的《1.4 Veri