fix: recover stale sessions without masking ARR submission errors

This commit is contained in:
Wyndham ARR committed 2026-10-08 21:04:34 +08:00
1 parent 5acedc02e0
commit 9487634f83
5 files changed
+140 -7

No files matched your search

+29 -4
View File
@@ -12,6 +12,7 @@
arrDownloadLoaded: false,
arrDownloadTask: null,
arrDownloadIntent: null,
arrDownloadSubmissionError: null,
arrDownloadBusy: false,
arrDownloadLoading: false,
arrDownloadConfigLoading: false,
@@ -415,11 +416,14 @@
let status = !state.arrDownloadLoaded ? "connecting" : !state.arrDownloadReady ? "unavailable" : task?.status || "ready";
if (state.arrDownloadConfigDisconnected) status = "service_reconnecting";
if (state.arrDownloadDisconnected || pending) status = "reconnecting";
const rejected = status === "not_received" && Boolean(task?.submission_error);
const feedback = $("#arr-download-feedback");
feedback.className = `arr-download-feedback${arrDownloadActive() ? " is-running" : status === "succeeded" ? " is-success" : ["needs_review", "needs_data_review"].includes(status) ? " is-review" : ["failed", "interrupted", "reconnecting", "service_reconnecting", "date_unavailable"].includes(status) ? " is-error" : ""}`;
feedback.className = `arr-download-feedback${arrDownloadActive() ? " is-running" : status === "succeeded" ? " is-success" : ["needs_review", "needs_data_review"].includes(status) ? " is-review" : ["failed", "interrupted", "reconnecting", "service_reconnecting", "date_unavailable"].includes(status) || rejected ? " is-error" : ""}`;
const taskError = !task?.job_id && status === "failed" && task.error_code === "ARR_SOURCE_FETCH_FAILED" ? "source_failed"
: !task?.job_id && status === "interrupted" && task.error_code === "ARR_DOWNLOAD_INTERRUPTED" ? "source_interrupted" : status;
const text = I18N.t(`arr_download.${taskError}`);
const text = rejected
? I18N.t("arr_download.submission_rejected", { reason: task.submission_error })
: I18N.t(`arr_download.${taskError}`);
const taskDate = task?.report_date || state.arrDownloadIntent?.report_date;
$("#arr-download-status").textContent = taskDate ? `${taskDate} · ${text}` : text;
$("#arr-download-review").hidden = task?.status !== "needs_review" || !task.job_id;
@@ -444,6 +448,7 @@
}
async function acceptARRDownloadTask(task, { sync = true } = {}) {
state.arrDownloadSubmissionError = null;
state.arrDownloadTask = task;
rememberARRPendingReview(task);
state.arrDownloadDisconnected = false;
@@ -481,6 +486,9 @@
if (state.arrDownloadIntent?.request_id !== intent.request_id) return;
if (error.status === 404) {
state.arrDownloadTask = { ...intent, status: "not_received", can_retry: false };
if (state.arrDownloadSubmissionError?.request_id === intent.request_id) {
state.arrDownloadTask.submission_error = state.arrDownloadSubmissionError.message;
}
state.arrDownloadDisconnected = false;
} else {
state.arrDownloadDisconnected = true;
@@ -514,6 +522,7 @@
state.arrDownloadContextId = config.context_id;
state.arrDownloadRestored = false;
state.arrDownloadIntent = null;
state.arrDownloadSubmissionError = null;
state.arrDownloadTask = null;
state.arrDownloadDisconnected = false;
state.arrDownloadSynced = "";
@@ -578,6 +587,7 @@
intent = { request_id: [...bytes].map((value) => value.toString(16).padStart(2, "0")).join(""), report_date: reportDate };
}
rememberARRIntent(intent); // Persist before the HTTP call, including a lost response.
state.arrDownloadSubmissionError = null;
state.arrDownloadTask = null;
resetARRDataReview();
state.arrDownloadBusy = true;
@@ -600,9 +610,12 @@
return;
}
// A dropped response is not evidence of a failed download/commit.
if (error.status >= 400 && error.status < 500) {
state.arrDownloadSubmissionError = { request_id: intent.request_id, message: error.message };
}
state.arrDownloadDisconnected = true;
if (error.status === 503) state.arrDownloadReady = false;
if ([400, 409, 503].includes(error.status)) showToast(error.message, true);
if ([400, 403, 409, 503].includes(error.status)) showToast(error.message, true);
await loadARRDownloadTask();
} finally {
state.arrDownloadBusy = false;
@@ -873,7 +886,7 @@
}
async function api(path, options = {}) {
const { returnEnvelope = false, ...requestOptions } = options;
const { returnEnvelope = false, csrfRetried = false, ...requestOptions } = options;
const headers = new Headers(requestOptions.headers || {});
if (requestOptions.method && requestOptions.method !== "GET") headers.set("X-ARR-CSRF", state.csrf);
const response = await fetch(path, { ...requestOptions, headers, credentials: "same-origin" });
@@ -892,6 +905,18 @@
const requestError = new Error(I18N?.errorMessage(error.code, error.message) || error.message || "请求未完成");
requestError.code = error.code || "";
requestError.status = response.status;
if (response.status === 403 && error.code === "SESSION_INVALID" && !csrfRetried
&& requestOptions.method && requestOptions.method !== "GET") {
// A fresh login in another tab changes the shared cookie, while this
// page may retain the old token. The rejected mutation did not run.
// Refresh only for the same user, then retry the exact request once.
let session;
try { session = await api("/api/session"); } catch (_) { throw requestError; }
if (session?.username !== state.arrDownloadUsername || !state.arrDownloadUsername
|| typeof session.csrf_token !== "string" || !session.csrf_token) throw requestError;
state.csrf = session.csrf_token;
return api(path, { ...options, csrfRetried: true });
}
throw requestError;
}
return returnEnvelope ? payload : payload.data;
+2 -1
View File
@@ -132,7 +132,8 @@
"arr_download.failed": ["任务未完成,请查看任务日志", "Task failed. Check the task log.", "งานไม่สำเร็จ โปรดดูบันทึกงาน"],
"arr_download.interrupted": ["任务中断,继续原任务以核对处理结果", "Task interrupted. Resume to reconcile the result.", "งานขัดจังหวะ ดำเนินงานเดิมต่อเพื่อตรวจสอบผล"],
"arr_download.reconnecting": ["正在重新查询原任务状态…", "Checking the original task status…", "กำลังตรวจสอบสถานะงานเดิม…"],
"arr_download.not_received": ["尚未查到任务,可继续提交原请求", "Task not found yet. Resubmit the original request.", "ยังไม่พบงาน สามารถส่งคำขอเดิมอีกครั้ง"],
"arr_download.not_received": ["下载任务尚未建立,请点击下方按钮重试", "The download task has not been created. Use the button below to retry.", "ยังไม่ได้สร้างงานดาวน์โหลด โปรดกดปุ่มด้านล่างเพื่อลองอีกครั้ง"],
"arr_download.submission_rejected": ["提交未成功:{reason}。下载任务尚未建立,请重试。", "Submission failed: {reason}. No download task has been created. Please retry.", "ส่งคำขอไม่สำเร็จ: {reason} ยังไม่ได้สร้างงานดาวน์โหลด โปรดลองอีกครั้ง"],
"arr_download.date_unavailable": ["本机模拟没有所选日期的数据,请重新选择日期。", "No local simulation data for this date. Choose another date.", "ไม่มีข้อมูลจำลองในเครื่องสำหรับวันที่นี้ โปรดเลือกวันที่อื่น"],
"arr_download.submitting": ["正在提交…", "Submitting…", "กำลังส่ง…"],
"arr_download.running": ["任务进行中", "In progress", "กำลังดำเนินการ"],