Kotlin+Reactor实现Gitlab分页Commits API遇无结果异常问题
解决Kotlin+Reactor调用Gitlab Commits API空结果异常问题
嘿,我来帮你搞定这个问题!你遇到的情况是:当两个提交哈希之间没有匹配的提交记录时,现有代码会抛出RuntimeException: Reached end of commit log,而你想通过switchIfEmpty来优雅处理这个空场景对吧?
问题根源分析
之前的异常大概率是因为你在分页遍历的过程中,一旦某一页返回空就直接抛出了异常,但正确的逻辑应该是遍历完所有分页后,确认整个流确实没有匹配结果时,再用switchIfEmpty处理。
修正后的代码示例
假设你已经有了调用单页Gitlab Commits API的函数,下面是处理两个哈希间提交、并正确处理空结果的完整实现:
// 先定义Gitlab提交数据类(根据API返回结构调整) data class GitlabCommit(val id: String, val message: String, val authorName: String) // 调用Gitlab单页提交API的函数 private fun getCommitsPage(projectId: String, page: Int, perPage: Int = 100): Flux<GitlabCommit> { return webClient.get() .uri("/projects/{projectId}/commits?page={page}&per_page={perPage}", projectId, page, perPage) .retrieve() .onStatus({ it.isError }) { clientResponse -> // 统一处理API错误,比如404、500等 clientResponse.bodyToMono(String::class.java) .map { errorMsg -> RuntimeException("Gitlab API error: $errorMsg") } } .bodyToFlux(GitlabCommit::class.java) } // 获取两个提交哈希之间的记录,正确处理空结果 fun getCommitsBetween(projectId: String, startHash: String, endHash: String): Flux<GitlabCommit> { return Flux.generate( { 1 }, // 初始页码从1开始 { currentPage, sink -> getCommitsPage(projectId, currentPage) .collectList() .subscribe({ pageCommits -> when { // 没有更多分页了,结束遍历 pageCommits.isEmpty() -> sink.complete() // 当前页包含起始哈希,过滤到该哈希为止并结束 pageCommits.any { it.id == startHash } -> { val filtered = pageCommits.takeWhile { it.id != startHash } .filter { it.id != endHash } // 排除结束哈希本身 filtered.forEach(sink::next) sink.complete() } // 当前页不包含起始哈希,过滤掉结束哈希后全部输出,继续下一页 else -> { val filtered = pageCommits.filter { it.id != endHash } filtered.forEach(sink::next) sink.next(currentPage + 1) } } }, { error -> // 传递API调用过程中的错误 sink.error(error) }) } ) .flatMapIterable { it } // 将分页的提交列表展开为Flux // 核心:当整个流为空时的处理逻辑,二选一即可 .switchIfEmpty(Flux.empty()) // 选项1:返回空流,上层自行处理空场景 // .switchIfEmpty(Flux.error(RuntimeException("No commits found between $startHash and $endHash"))) // 选项2:抛出自定义异常 }
关键优化点
- 分页遍历逻辑:用
Flux.generate来逐页遍历Gitlab API,直到没有更多页或者找到起始哈希,避免提前抛出异常。 - 空结果触发时机:只有当所有分页都遍历完成、且没有任何匹配的提交时,
switchIfEmpty才会生效,这才是正确的空场景判断时机。 - 错误统一处理:在
getCommitsPage里通过onStatus处理API的错误响应,避免未捕获的异常中断流程。 - 灵活的空结果处理:你可以选择返回空流让上层处理,或者直接抛出自定义异常,完全根据业务需求调整。
额外注意事项
- Gitlab API的
per_page参数最大支持100,设置成100可以减少分页请求次数。 - 要确认提交哈希的顺序:如果
startHash是比endHash更新的提交,当前逻辑是从新到旧遍历,如果你需要反向遍历,需要调整API的order_by和sort参数(比如order_by=created_at&sort=asc)。
内容的提问来源于stack exchange,提问作者feob
相关产品推荐
相关产品推荐

