From 9311a9e7f9578aff5c9d9d2e2ed656014a5de431 Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Thu, 19 Oct 2023 20:40:18 +0800 Subject: [PATCH] Implement download timeout --- .../kotlin/com/hippo/ehviewer/Settings.kt | 1 + .../com/hippo/ehviewer/spider/SpiderQueen.kt | 29 ++++++++++++------- .../ehviewer/ui/settings/DownloadScreen.kt | 7 +++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt b/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt index f6d7a89e7..44487d8d0 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt @@ -34,6 +34,7 @@ object Settings : DataStorePreferences(null) { var gallerySite by intPref("gallery_site_2", 0).observed { updateWhenGallerySiteChanges() } var multiThreadDownload by intPref("download_thread_2", 3) var preloadImage by intPref("preload_image_2", 5) + var downloadTimeout by intPref("download_timeout", 60) var theme by intPref("theme_2", -1).observed { updateWhenThemeChanges() } var listMode by intPref("list_mode_2", 0) var detailSize by intPref("detail_size_2", 0) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt index 25367a05e..0de014ae4 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/spider/SpiderQueen.kt @@ -46,6 +46,7 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.cancel import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.delay @@ -55,10 +56,12 @@ 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 splitties.init.appCtx import java.time.Instant import java.util.concurrent.atomic.AtomicInteger +import kotlin.time.Duration.Companion.seconds class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineScope { override val coroutineContext = Dispatchers.IO + Job() @@ -520,6 +523,7 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS private var showKey: String? = null private val showKeyLock = Mutex() private val mDownloadDelay = Settings.downloadDelay.toLong() + private val downloadTimeout = Settings.downloadTimeout.seconds private val delayLock = Mutex() private var delayedTime = 0L private var isDownloadMode = false @@ -689,12 +693,14 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS repeat(3) { times -> runCatching { Log.d(WORKER_DEBUG_TAG, "Start download image $index attempt #$times") - val success = mSpiderDen.makeHttpCallAndSaveImage( - index, - targetImageUrl, - referer, - this@SpiderQueen::notifyPageDownload.partially1(index), - ) + val success = withTimeout(downloadTimeout) { + mSpiderDen.makeHttpCallAndSaveImage( + index, + targetImageUrl, + referer, + this@SpiderQueen::notifyPageDownload.partially1(index), + ) + } check(success) Log.d(WORKER_DEBUG_TAG, "Download image $index succeed") @@ -702,11 +708,11 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS return }.onFailure { mSpiderDen.remove(index) - if (it is CancellationException) { - throw it - } else { - Log.d(WORKER_DEBUG_TAG, "Download image $index attempt #$times failed") - error = ExceptionUtils.getReadableString(it) + Log.d(WORKER_DEBUG_TAG, "Download image $index attempt #$times failed") + error = when (it) { + is TimeoutCancellationException -> ERROR_TIMEOUT + is CancellationException -> throw it + else -> ExceptionUtils.getReadableString(it) } } } @@ -769,6 +775,7 @@ 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_ARRAY = arrayOf( "https://ehgt.org/g/509.gif", diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt index 21fe5d258..73daf0a89 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/settings/DownloadScreen.kt @@ -139,6 +139,13 @@ fun DownloadScreen() { entryValueRes = R.array.download_delay_entry_values, value = downloadDelay, ) + IntSliderPreference( + maxValue = 120, + minValue = 10, + step = 10, + title = stringResource(id = R.string.settings_download_download_timeout), + value = Settings::downloadTimeout, + ) val preloadImage = Settings::preloadImage.observed SimpleMenuPreferenceInt( title = stringResource(id = R.string.settings_download_preload_image), diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f9e55b509..85bd46583 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -485,6 +485,7 @@ 全部开始(倒序) 下载延时 每次下载延时 %s 毫秒 + 下载超时(秒) 请安装一个浏览器。 从始至终 过去一年 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d9dd03b08..fe828ffd1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -399,6 +399,7 @@ Up to %s images Download delay Delay %s ms per download + Download timeout (in seconds) Preload image Preload next %s image Download original image