Add market watch and match hub workflows
这个提交包含在:
@@ -9,6 +9,20 @@ function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function isRetriableBackgroundError(error: unknown) {
|
||||
if (!(error instanceof Error)) return false;
|
||||
return (
|
||||
error.message.startsWith("Request timed out after ") ||
|
||||
error.message.includes("fetch failed") ||
|
||||
error.message.includes("ECONNRESET") ||
|
||||
error.message.includes("ETIMEDOUT") ||
|
||||
error.message.includes("429") ||
|
||||
error.message.includes("502") ||
|
||||
error.message.includes("503") ||
|
||||
error.message.includes("504")
|
||||
);
|
||||
}
|
||||
|
||||
async function workOnce() {
|
||||
await db.failExhaustedBackgroundTasks();
|
||||
await db.requeueStaleBackgroundTasks(new Date(Date.now() - ENV.backgroundTaskStaleMs));
|
||||
@@ -31,9 +45,21 @@ async function workOnce() {
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Unknown background task error";
|
||||
await db.failBackgroundTask(task.id, message);
|
||||
await db.failVisionTestRun(task.id, message);
|
||||
console.error(`[worker] task ${task.id} failed:`, error);
|
||||
if (isRetriableBackgroundError(error) && task.attempts < task.maxAttempts) {
|
||||
const nextAttempt = task.attempts + 1;
|
||||
const delayMs = Math.min(30_000, 5_000 * task.attempts);
|
||||
await db.rescheduleBackgroundTask(task.id, {
|
||||
progress: 15,
|
||||
message: `请求超时,已自动重试(第 ${nextAttempt}/${task.maxAttempts} 次尝试)`,
|
||||
error: message,
|
||||
delayMs,
|
||||
});
|
||||
console.warn(`[worker] task ${task.id} rescheduled after retriable error:`, error);
|
||||
} else {
|
||||
await db.failBackgroundTask(task.id, message);
|
||||
await db.failVisionTestRun(task.id, message);
|
||||
console.error(`[worker] task ${task.id} failed:`, error);
|
||||
}
|
||||
} finally {
|
||||
clearInterval(heartbeatTimer);
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户