Mirror: медленный list(500) не роняет каталог и не дёргается в цикле

- отдельный defaultMirrorHttpClient (connect 15с / request 90с) + 1 повтор на list():
  тяжёлый GET /api/mirror?limit=N на сервере дольше общего 30с-таймаута и подёргивается (503);
- каталог: зеркала грузятся в отдельном try — сбой/таймаут не чистит уже загруженный каталог,
  просто временно без бейджей;
- детали: убрали тяжёлый list(limit=500) каждые 3 с (progress зеркала на сервере не живой, 0
  до конца) — в цикле опрашивается только дешёвый mirrorByItem.
This commit is contained in:
2026-09-02 23:02:56 +03:00
parent 40723fa584
commit 0b3f9ff975
4 changed files with 70 additions and 12 deletions
@@ -52,6 +52,7 @@ import pw.binom.viewmate.core.media.MirrorJob
import pw.binom.viewmate.core.protocol.DownloadPhase
import pw.binom.viewmate.phone.PhoneApp
import pw.binom.viewmate.phone.WatchProgress
import pw.binom.viewmate.phone.log
/** Вкладки каталога: Фильмы / Сериалы / Папки. */
enum class CatalogTab { MOVIES, SERIES, FOLDERS }
@@ -205,7 +206,6 @@ class CatalogState(
}
}
items = loaded
mirrors = app.mirror.list(limit = 500).associateBy { it.itemId.orEmpty() }
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
@@ -214,6 +214,15 @@ class CatalogState(
} finally {
loading = false
}
// Зеркала — отдельный «мягкий» запрос: сбой/таймаут mirror.list не чистит
// уже загруженный каталог, просто временно без бейджей.
try {
mirrors = app.mirror.list(limit = 500).associateBy { it.itemId.orEmpty() }
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
log("catalog", "зеркала: не удалось (${e.message}) — каталог без бейджей")
}
}
}
@@ -78,16 +78,16 @@ fun DetailsScreen(
val glassesDownloadedIds by app.server.hub.downloadedItemIds.collectAsState()
val glassesMediaDir by app.server.hub.mediaDir.collectAsState()
// статус зеркала + дорожки; пока конвертируется — опрашиваем
// статус зеркала + дорожки; пока конвертируется — опрашиваем только дешёвый byItem.
// Тяжёлый list(limit=500) НЕ дёргаем каждые 3 с: progress зеркала на сервере не живой
// (0 до конца), а тяжёлый запрос с большим лимитом — главный источник таймаутов.
LaunchedEffect(item.Id, refreshKey) {
loading = true
mirrorStatus = runCatching { app.mirror.mirrorByItem(item.Id) }.getOrNull()
mirrorJob = runCatching { app.mirror.list(limit = 500).firstOrNull { it.itemId == item.Id } }.getOrNull()
loading = false
while (mirrorStatus?.status == "processing" || mirrorStatus?.status == "queued") {
delay(3_000)
mirrorStatus = runCatching { app.mirror.mirrorByItem(item.Id) }.getOrNull()
mirrorJob = runCatching { app.mirror.list(limit = 500).firstOrNull { it.itemId == item.Id } }.getOrNull()
}
}