Use ktor plugin for download timeout

This commit is contained in:
FooIbar committed 2024-10-28 00:00:48 +08:00
1 parent b6f84d8de6
commit 9f4faebfe6
5 files changed
+33 -21

No files matched your search

@@ -3,10 +3,14 @@ package com.hippo.ehviewer.ktor
import com.hippo.ehviewer.client.EhCookieStore
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.HttpClientEngineConfig
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.cookies.HttpCookies
fun <T : HttpClientEngineConfig> HttpClientConfig<T>.configureCommon() = apply {
install(HttpCookies) {
storage = EhCookieStore
}
install(HttpTimeout) {
requestTimeoutMillis = 10_000
}
}
@@ -12,6 +12,7 @@ import android.os.Build
import androidx.annotation.RequiresExtension
import io.ktor.client.engine.HttpClientEngineBase
import io.ktor.client.engine.callContext
import io.ktor.client.plugins.HttpTimeoutCapability
import io.ktor.client.request.HttpRequestData
import io.ktor.client.request.HttpResponseData
import io.ktor.http.HttpHeaders
@@ -41,6 +42,9 @@ import kotlinx.coroutines.suspendCancellableCoroutine
class CronetEngine(override val config: CronetConfig) : HttpClientEngineBase("Cronet") {
// Limit thread to 1 since we are async & non-blocking
override val dispatcher = Dispatchers.Default.limitedParallelism(1)
override val supportedCapabilities = setOf(HttpTimeoutCapability)
private val executor = dispatcher.asExecutor()
private val pool = DirectByteBufferPool(32)
private val client by lazy {
@@ -52,6 +52,7 @@ import com.hippo.files.openFileDescriptor
import com.hippo.files.openOutputStream
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.plugins.onDownload
import io.ktor.client.plugins.timeout
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.bodyAsChannel
import io.ktor.client.statement.request
@@ -71,6 +72,7 @@ class SpiderDen(val info: GalleryInfo) {
private var tempDownloadDir: Path? = null
private val saveAsCbz = Settings.saveAsCbz
private val archiveName = "$gid.cbz"
private val downloadTimeout = Settings.downloadTimeout * 1000L
private val lock = ReentrantReadWriteLock()
@@ -174,6 +176,9 @@ class SpiderDen(val info: GalleryInfo) {
notifyProgress(total!!, done, (done - prev).toInt())
prev = done
}
timeout {
requestTimeoutMillis = downloadTimeout
}
}.executeSafely {
if (it.status.isSuccess()) {
saveFromHttpResponse(index, it)
@@ -42,14 +42,12 @@ import com.hippo.files.find
import eu.kanade.tachiyomi.util.system.logcat
import java.util.concurrent.atomic.AtomicInteger
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.TimeSource
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.currentCoroutineContext
@@ -60,7 +58,6 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.sync.withPermit
import kotlinx.coroutines.withTimeout
import moe.tarsin.coroutines.runSuspendCatching
import okio.Path
import splitties.init.appCtx
@@ -502,7 +499,6 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
private var showKey: String? = null
private val showKeyLock = Mutex()
private val mDownloadDelay = Settings.downloadDelay.milliseconds
private val downloadTimeout = Settings.downloadTimeout.seconds
private var lastRequestTime = TimeSource.Monotonic.markNow()
var isDownloadMode = false
private set
@@ -670,14 +666,12 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
repeat(2) { times ->
runCatching {
logcat(WORKER_DEBUG_TAG) { "Start download image $index attempt #$times" }
val success = withTimeout(downloadTimeout) {
mSpiderDen.makeHttpCallAndSaveImage(
index,
targetImageUrl,
referer,
this@SpiderQueen::notifyPageDownload.partially1(index),
)
}
val success = mSpiderDen.makeHttpCallAndSaveImage(
index,
targetImageUrl,
referer,
this@SpiderQueen::notifyPageDownload.partially1(index),
)
check(success)
logcat(WORKER_DEBUG_TAG) { "Download image $index succeed" }
@@ -686,11 +680,8 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
}.onFailure {
mSpiderDen.removeIntermediateFiles(index)
logcat(WORKER_DEBUG_TAG) { "Download image $index attempt #$times failed" }
error = when (it) {
is TimeoutCancellationException -> ERROR_TIMEOUT
is CancellationException -> throw it
else -> it.displayString()
}
if (it is CancellationException) throw it
error = it.displayString()
}
}
}
@@ -758,7 +749,6 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
}
private val PTOKEN_FAILED_MESSAGE = appCtx.getString(R.string.error_get_ptoken_error)
private val ERROR_TIMEOUT = appCtx.getString(R.string.error_timeout)
private val DECODE_ERROR = appCtx.getString(R.string.error_decoding_failed)
private val URL_509_PATTERN = Regex("\\.org/.+/509s?\\.gif")
private const val FORCE_RETRY = "Force retry"
@@ -17,9 +17,18 @@ package com.hippo.ehviewer.util
import com.hippo.ehviewer.R
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.client.network.sockets.ConnectTimeoutException
import io.ktor.client.network.sockets.SocketTimeoutException
import io.ktor.client.plugins.HttpRequestTimeoutException
import splitties.init.appCtx
fun Throwable.displayString(): String {
logcat(this)
return message ?: appCtx.getString(R.string.error_unknown)
fun Throwable.displayString(): String = when (this) {
is HttpRequestTimeoutException,
is ConnectTimeoutException, is SocketTimeoutException,
-> appCtx.getString(R.string.error_timeout)
else -> {
logcat(this)
message ?: appCtx.getString(R.string.error_unknown)
}
}