fix(catalog) : show asset progress and retry transient failures
This commit is contained in:
+11
-7
@@ -115,7 +115,7 @@ interface SyncedCharacter {
|
||||
|
||||
type SyncControl = { signal?: AbortSignal; checkCancelled: () => Promise<void>; report: (phase: string, completed: number, total: number, message: string) => Promise<void> };
|
||||
|
||||
async function retryTimeout<T>(label: string, task: () => Promise<T>, signal?: AbortSignal): Promise<T> {
|
||||
async function retryTransient<T>(label: string, task: () => Promise<T>, signal?: AbortSignal): Promise<T> {
|
||||
for (let attempt = 1; ; attempt += 1) {
|
||||
signal?.throwIfAborted();
|
||||
try {
|
||||
@@ -123,7 +123,7 @@ async function retryTimeout<T>(label: string, task: () => Promise<T>, signal?: A
|
||||
} catch (cause) {
|
||||
signal?.throwIfAborted();
|
||||
const message = cause instanceof Error ? cause.message : String(cause);
|
||||
if (attempt >= 3 || !/timed out|timeout/i.test(message)) {
|
||||
if (attempt >= 3 || !/timed out|timeout|unexpected error has occurred/i.test(message)) {
|
||||
throw new Error(`${label}: ${message}`, { cause });
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, attempt * 1_000));
|
||||
@@ -132,7 +132,7 @@ async function retryTimeout<T>(label: string, task: () => Promise<T>, signal?: A
|
||||
}
|
||||
|
||||
async function getJson(url: string, signal?: AbortSignal): Promise<unknown> {
|
||||
return retryTimeout(`Lunaris request ${url}`, async () => {
|
||||
return retryTransient(`Lunaris request ${url}`, async () => {
|
||||
const response = await fetch(url, {
|
||||
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(60_000)]) : AbortSignal.timeout(60_000),
|
||||
cache: "no-store",
|
||||
@@ -144,7 +144,7 @@ async function getJson(url: string, signal?: AbortSignal): Promise<unknown> {
|
||||
}
|
||||
|
||||
async function getOptionalJson(url: string, signal?: AbortSignal): Promise<unknown | null> {
|
||||
return retryTimeout(`Lunaris request ${url}`, async () => {
|
||||
return retryTransient(`Lunaris request ${url}`, async () => {
|
||||
const response = await fetch(url, {
|
||||
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(60_000)]) : AbortSignal.timeout(60_000),
|
||||
cache: "no-store",
|
||||
@@ -229,12 +229,15 @@ async function uploadAssets(
|
||||
let completed = 0;
|
||||
let lastProgressAt = 0;
|
||||
const missing = new Set<string>();
|
||||
async function reportProgress() {
|
||||
async function reportProgress(currentAsset?: string) {
|
||||
if (!control) return;
|
||||
const now = Date.now();
|
||||
if (completed < assets.length && now - lastProgressAt < PROGRESS_INTERVAL_MS) return;
|
||||
lastProgressAt = now;
|
||||
await control.report("assets", completed, assets.length, `ดาวน์โหลดรูปภาพ ${completed}/${assets.length}`);
|
||||
const message = currentAsset
|
||||
? `กำลังดาวน์โหลดรูปภาพ ${Math.min(completed + 1, assets.length)}/${assets.length}\n${currentAsset.split("/").at(-1)}`
|
||||
: `ดาวน์โหลดรูปภาพ ${completed}/${assets.length}`;
|
||||
await control.report("assets", completed, assets.length, message);
|
||||
}
|
||||
async function worker() {
|
||||
while (true) {
|
||||
@@ -242,7 +245,8 @@ async function uploadAssets(
|
||||
if (index >= assets.length) return;
|
||||
await control?.checkCancelled();
|
||||
const asset = assets[index];
|
||||
await retryTimeout(`Asset ${asset.target}`, async () => {
|
||||
await reportProgress(asset.target);
|
||||
await retryTransient(`Asset ${asset.target}`, async () => {
|
||||
if (!(await storage.file(asset.target).exists())) {
|
||||
if (asset.body) {
|
||||
await storage.write(asset.target, asset.body, {
|
||||
|
||||
Reference in New Issue
Block a user