fix: recover stale sessions without masking ARR submission errors
This commit is contained in:
1 parent
5acedc02e0
commit
9487634f83
5 files changed
+140
-7
No files matched your search
+29
-4
@@ -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;
|
||||
|
||||
@@ -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", "กำลังดำเนินการ"],
|
||||
|
||||
Reference in new issue
Block a user