From e84d87a8835b2f31e11863d771fd28b74b128699 Mon Sep 17 00:00:00 2001 From: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> Date: Wed, 25 Jun 2025 00:34:21 +0500 Subject: [PATCH] Hitomi: retry on stream reset exception with internal error from server (#9414) * retry with delay on internal_error from server * bump * else --- src/all/hitomi/build.gradle | 2 +- .../tachiyomi/extension/all/hitomi/Hitomi.kt | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/all/hitomi/build.gradle b/src/all/hitomi/build.gradle index d0e3c40a6..70924cede 100644 --- a/src/all/hitomi/build.gradle +++ b/src/all/hitomi/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Hitomi' extClass = '.HitomiFactory' - extVersionCode = 39 + extVersionCode = 40 isNsfw = true } diff --git a/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt b/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt index 54a120268..42a540e2b 100644 --- a/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt +++ b/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt @@ -15,6 +15,7 @@ import keiyoushi.utils.tryParse import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -24,6 +25,7 @@ import okhttp3.HttpUrl import okhttp3.Interceptor import okhttp3.Request import okhttp3.Response +import okhttp3.internal.http2.ErrorCode import okhttp3.internal.http2.StreamResetException import rx.Observable import java.nio.ByteBuffer @@ -53,9 +55,6 @@ class Hitomi( override val client = network.cloudflareClient.newBuilder() .addInterceptor(::imageUrlInterceptor) - .apply { - interceptors().add(0, ::streamResetRetry) - } .build() override fun headersBuilder() = super.headersBuilder() @@ -118,7 +117,22 @@ class Hitomi( } } - return client.newCall(request).awaitSuccess().use { it.body.bytes() } + val tries = 5 + repeat(tries) { attempt -> + try { + return client.newCall(request).awaitSuccess().use { it.body.bytes() } + } catch (e: StreamResetException) { + if (e.errorCode == ErrorCode.INTERNAL_ERROR) { + if (attempt == tries - 1) throw e // last attempt, rethrow + Log.e(name, "Stream reset attempt ${attempt + 1}", e) + delay((attempt + 1).seconds) + } else { + throw e + } + } + } + + throw Exception("Unreachable code") } private suspend fun hitomiSearch( @@ -667,20 +681,6 @@ class Hitomi( return hash.replace(Regex("""^.*(..)(.)$"""), "$2/$1") } - private fun streamResetRetry(chain: Interceptor.Chain): Response { - return try { - chain.proceed(chain.request()) - } catch (e: StreamResetException) { - Log.e(name, "reset", e) - if (e.message.orEmpty().contains("INTERNAL_ERROR")) { - Thread.sleep(2.seconds.inWholeMilliseconds) - chain.proceed(chain.request()) - } else { - throw e - } - } - } - private fun imageUrlInterceptor(chain: Interceptor.Chain): Response { val request = chain.request() if (request.url.host != IMAGE_LOOPBACK_HOST) {