fix(frontend): keep regen in-flight lock on client disconnect (tab switch)

Made-with: Cursor
This commit is contained in:
hub-gif 2026-04-14 14:20:17 +08:00
parent fdf5901f76
commit 4847003a05
2 changed files with 28 additions and 8 deletions

View File

@ -58,6 +58,20 @@ export function generationInFlightKey() {
return inFlightKey
}
/**
* 切换页签/隐藏标签时浏览器可能中止 fetch表现为 TypeError 此时服务端可能仍在执行
* 不应清除进行中标记否则按钮误恢复可点HTTP 4xx/5xx 仍由业务层 return走正常清除
*/
function isAmbiguousClientFailure(err) {
if (err == null) return false
const name = err.name || ''
if (name === 'AbortError') return true
const msg = String(err.message || err)
return /Failed to fetch|NetworkError|Load failed|ERR_NETWORK|INTERNET_DISCONNECTED|aborted|cancel/i.test(
msg,
)
}
/**
* @param {string} key
* @param {() => Promise<T>} fn
@ -67,11 +81,17 @@ export async function withGenerationInFlight(key, fn) {
inFlightKey.value = key
writePersisted(key)
try {
return await fn()
} finally {
const out = await fn()
if (inFlightKey.value === key) {
inFlightKey.value = null
writePersisted(null)
}
return out
} catch (e) {
if (inFlightKey.value === key && !isAmbiguousClientFailure(e)) {
inFlightKey.value = null
writePersisted(null)
}
throw e
}
}

View File

@ -156,8 +156,8 @@ async function regenerateReport() {
if (!id) return
regenErr.value = ''
const key = `${REGEN_PREFIX}${id}`
await withGenerationInFlight(key, async () => {
try {
try {
await withGenerationInFlight(key, async () => {
const r = await api(`/api/jobs/${id}/regenerate-report/`, {
method: 'POST',
body: JSON.stringify({
@ -177,10 +177,10 @@ async function regenerateReport() {
const updated = JSON.parse(text)
const idx = jobs.value.findIndex((x) => x.id === updated.id)
if (idx >= 0) jobs.value[idx] = updated
} catch (e) {
regenErr.value = String(e)
}
})
})
} catch (e) {
regenErr.value = String(e)
}
}
onMounted(loadList)