Kotlin协程:暂停后续访问令牌续订请求

时间:2019-09-12 12:08:40

标签: kotlin kotlin-coroutines

我有一个应用程序,该应用程序通过后端进行身份验证,并收到一个长期的刷新令牌和一个短暂的访问令牌。我们使用访问令牌来授权请求​​,并且每次过期时,我们都会触发令牌更新(使用刷新令牌),然后使用新令牌重试API调用。很标准的东西。

可以同时(异步)触发多个网络调用,但是如果它们都具有无效的访问令牌,我们只希望第一个通过并刷新令牌,而后续的调用则等待初始的调用完成才可以继续。目前,我们已经实现了以下方式:

private var renewingDeferred: Deferred<Unit>? = null

suspend fun renewTokens() {
    coroutineScope {
        if (renewingDeferred == null) {
            renewingDeferred = async {
                try {
                    tokens = tokensApi.renew().await()
                } finally {
                    renewingDeferred = null
                }
            }
        } else {
            renewingDeferred?.await()
        }
    }
}

这个想法是,每个具有无效访问令牌的请求都将调用renewTokens(),然后使用新的标头重试。只要renewTokens()的调用者知道函数一旦返回(即不再挂起)就更新令牌,它就不必关心它实际上是更新还是只是等待先前的更新完成。据我所知,它可以正常工作,但是我不确定代码,特别是renewingDeferred = null块的finally部分。

例如,假设请求A开始更新,请求B被触发并开始等待请求A,然后A完成,将renewingDeferred设置为null,但确实将该值设置为null会以某种方式影响请求B的等待状态吗?

此外,如果在调用API时抛出异常怎么办?我没有catch块,有点假设await()在延迟的抛出上会以某种方式重新抛出,但是协程中的异常处理并不是我的强项。希望就此获得一些建议。

此外,如果有人对应该如何以其他方式解决此问题有一个一般的想法,欢迎提出所有建议!

1 个答案:

答案 0 :(得分:0)

您可以使用Mutex解决此问题。 创建一个用于协程锁定的属性,并在调用renewToken时锁定Mutex,直到令牌更新为止。