temporaryなめも帳

だらだらと備忘録とか。誰かの為になることをねがって。

RxJavaでエラーが発生したときに◯回リトライする

ただのメモ書き。

やりたいこと

エラーが発生したときに◯回リトライして、エラー終了 or 正常終了する 全てはこのあたりにまとまっている。ただの蛇足

qiita.com

qiita.com

試したこと

目的は、Httpリクエストにつけてるtokenの期限切れ時にリトライするようなパターンを想定している。 書いてみたら、結局は上記の記事の内容で十分網羅出来ている

正常終了のパターン

@RunWith(JUnit4::class)
class MyTest {

    fun someFunction() {
        System.out.println("some")
    }

    @Test
    fun hoge() {
        val exception = mock(HttpException::class.java).apply {
            `when`(code()).thenReturn(HttpURLConnection.HTTP_UNAUTHORIZED)
        }

        Observable.create<String> {
            it.onNext("1")
            it.onNext("2")
            it.onError(exception)
        }.retryWhen { upstream ->
            upstream.take(3).doOnNext {
                if (it is HttpException) {
                    when (it.code()) {
                        HttpURLConnection.HTTP_UNAUTHORIZED -> someFunction()
                    }
                }
            }
        }.subscribe({
            System.out.println(it)
        }, {
            System.out.println("error")
        }, {
            System.out.println("completed")
        })
    }
}

結果

1
2
some
1
2
some
1
2
some
completed

エラー終了のパターン。こちらはcomposeを利用するようにしてみてる

@RunWith(JUnit4::class)
class MyTest {

    fun someFunction() {
        System.out.println("some")
    }

    @Test
    fun fuga() {
        val exception = mock(HttpException::class.java).apply {
            `when`(code()).thenReturn(HttpURLConnection.HTTP_UNAUTHORIZED)
        }

        Single.create<String> { emitter ->
            System.out.println("st")
            emitter.onError(exception)
        }
                .compose(TokenRefreshTransformer<String>())
                .subscribe({
                    System.out.println(it)
                }, {
                    System.out.println("error occurred")
                })
    }
}
class TokenRefreshTransformer<T> : SingleTransformer<T, T> {
    override fun apply(upstream: Single<T>): SingleSource<T> =
            upstream.retry { count, it -> refresh(count, it) }

    private fun refresh(count: Int, throwable: Throwable): Boolean {
        if (count < 3) {
            if (throwable is HttpException) {
                when (throwable.code()) {
                    HttpURLConnection.HTTP_UNAUTHORIZED -> someFunction()
                }
            }
            return true
        }
        return false
    }

    private fun someFunction() {
        System.out.println("super!")
    }
}

結果

st
super!
st
super!
st
error occurred