feat(metadata): skip models on offline roots during bulk fetch (#1108)

Bulk metadata refresh picked candidates purely from cache state, so the
entries the scoped scan deliberately keeps for unreachable drives were
fetched anyway — burning CivitAI rate limit on sidecar/preview writes
that cannot land.

- Filter the fetch queue by root reachability (live check via
  describe_model_roots), covering both startup-offline and mid-session
  drive-off; probing failures degrade to no filtering
- Report offline_skipped / offline_roots in the WS terminal payloads,
  the HTTP result and the completion message
- Show a "Drive Offline" stat card in the fetch summary modal when
  any model was skipped this way
This commit is contained in:
Will Miao
2026-10-08 07:47:54 +08:00
parent 842ffb1df8
commit 3468686e5f
14 changed files with 243 additions and 6 deletions
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "Erfolgreich",
"statFailed": "Fehlgeschlagen",
"statSkipped": "Übersprungen",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "Gesamt geprüft",
"statDuration": "Dauer",
"successMessage": "Alle {count} {type}s erfolgreich aktualisiert!",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "Success",
"statFailed": "Failed",
"statSkipped": "Skipped",
"statOffline": "Drive Offline",
"statTotal": "Total Scanned",
"statDuration": "Duration",
"successMessage": "All {count} {type}s updated successfully!",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "Éxito",
"statFailed": "Fallido",
"statSkipped": "Omitido",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "Total escaneado",
"statDuration": "Duración",
"successMessage": "¡Todos los {count} {type}s actualizados correctamente!",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "Réussi",
"statFailed": "Échoué",
"statSkipped": "Ignoré",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "Total scanné",
"statDuration": "Durée",
"successMessage": "Tous les {count} {type}s mis à jour avec succès !",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "הצלחה",
"statFailed": "נכשל",
"statSkipped": "דולג",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "סה\"כ נסרק",
"statDuration": "משך",
"successMessage": "כל {count} {type}s עודכנו בהצלחה!",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "成功",
"statFailed": "失敗",
"statSkipped": "スキップ",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "スキャン合計",
"statDuration": "所要時間",
"successMessage": "すべての{count}件の{type}を正常に更新しました",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "성공",
"statFailed": "실패",
"statSkipped": "건너뜀",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "총 스캔",
"statDuration": "소요 시간",
"successMessage": "모든 {count}개 {type}이(가) 성공적으로 업데이트되었습니다",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "Успешно",
"statFailed": "Ошибка",
"statSkipped": "Пропущено",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "Всего проверено",
"statDuration": "Длительность",
"successMessage": "Все {count} {type}s успешно обновлены",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "成功",
"statFailed": "失败",
"statSkipped": "已跳过",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "总计扫描",
"statDuration": "耗时",
"successMessage": "全部 {count} 个 {type} 更新成功!",
+1
View File
@@ -2130,6 +2130,7 @@
"statSuccess": "成功",
"statFailed": "失敗",
"statSkipped": "已跳過",
"statOffline": "[TODO: Translate] Drive Offline",
"statTotal": "總計掃描",
"statDuration": "耗時",
"successMessage": "全部 {count} 個 {type} 更新成功!",