0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OkHttp3の再認証処理でRetrofit2のCoroutine実装を使うと通信が詰まる

Posted at

概要

OkHttp3のAuthenticatorを使って再認証処理を書いている場合に、Retrofit2のRx実装からCoroutine実装に変更すると認証処理が詰まってそれ以後のすべての通信ができなくなることがあります。

変更内容

変更前

interface Api {
    @Post("authorize")
    fun authorize(): Single<Token>
}

class TokenRefreshAuthenticator @Inject constructor(
    private val api: Api
): Authenticator {
    override fun authenticate(route: Route?, response: Response): Request?
        val token = api.authorize().blockingGet()

        // Tokenを使った処理
    }
}

変更後

interface Api {
    @Post("authorize")
    suspend fun authorize(): Token
}

class TokenRefreshAuthenticator @Inject constructor(
    private val api: Api
): Authenticator {
    override fun authenticate(route: Route?, response: Response): Request?
        val token = runBlocking { api.authorize() }

        // Tokenを使った処理
    }
}

対処法

単純なのはCoroutine実装を使うのをやめてCallで直接呼びましょう

interface Api {
    @Post("authorize")
    fun authorize(): Call<Token>
}

class TokenRefreshAuthenticator @Inject constructor(
    private val api: Api
): Authenticator {
    override fun authenticate(route: Route?, response: Response): Request?
        val token = api.authorize().execute().body()

        // Tokenを使った処理
    }
}

原因

Retrofit2のRx実装とCoroutine実装の違いにあります。Rx実装では同時呼び出しに上限がありませんが、Coroutine実装には同時実装の呼び出し上限があり、認証切れ時に大量のAPI呼び出しを行うと再認証処理が同時に走り再認証待ちとAPIの処理待ちのデッドロック状態になってしまいます。

ちょっとした変更なのに詰まるっていうのはどうかと思いますが、ハマると辛いので誰かの役に立つと嬉しいです。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?