Keep watching the job through transient fetch failures; don't freeze the screen
reprocessInPlace's poll loop swallowed fetchJobs failures as an empty list and broke on the resulting missing status, so ONE dropped poll during a 10-minute summarize ended the watch early: chips stayed disabled, the screen showed stale content, and only leaving to the library and back (fresh openDetail fetch) displayed the finished summary — the exact reported symptom. Now only a successful fetch reporting a terminal state ends the loop; transient failures keep polling for ~30s, and a genuinely-lost engine says so in plain words instead of silently stranding the screen. A missing job row on healthy fetches gets 3 grace cycles before giving up (engine rewrites rows mid-requeue).
This commit is contained in:
parent
70483b4cf8
commit
b5836d0fb6
1 changed files with 26 additions and 4 deletions
|
|
@ -1632,11 +1632,30 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
|
|||
return@launch
|
||||
}
|
||||
}
|
||||
// Poll the target job to a terminal state.
|
||||
// Poll the target job to a terminal state. A job this long
|
||||
// (10+ min = hundreds of polls) WILL hit a transient fetch
|
||||
// failure; treating one as terminal (the old `orEmpty()` →
|
||||
// st == null → break) froze the screen on stale content until
|
||||
// the user left and returned — exactly the reported symptom.
|
||||
// So: only a SUCCESSFUL fetch reporting a terminal state
|
||||
// breaks; failures keep polling up to ~30s of contact loss.
|
||||
var miss = 0
|
||||
var gone = 0
|
||||
while (true) {
|
||||
delay(2000)
|
||||
val jobs = runCatching { parseJobs(provider.fetchJobs(remoteId)) }.getOrNull()
|
||||
.orEmpty()
|
||||
val fetched = runCatching { parseJobs(provider.fetchJobs(remoteId)) }
|
||||
if (fetched.isFailure) {
|
||||
if (++miss >= 15) {
|
||||
d0.error = "Lost contact with the engine while " +
|
||||
"processing — reopen this recording to check."
|
||||
d0.busy = null
|
||||
_detail.value = d0.copy()
|
||||
return@launch
|
||||
}
|
||||
continue
|
||||
}
|
||||
miss = 0
|
||||
val jobs = fetched.getOrDefault(emptyList())
|
||||
d0.jobs = jobs
|
||||
jobLabel(jobs)?.let { d0.busy = it }
|
||||
// Mirror live progress onto the library row too — otherwise
|
||||
|
|
@ -1646,7 +1665,10 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
|
|||
rescanStatuses()
|
||||
_detail.value = d0.copy()
|
||||
val st = jobs.firstOrNull { it.jobType == job }?.status
|
||||
if (st == null || st in TERMINAL) break
|
||||
if (st in TERMINAL) break
|
||||
// Job row missing from a healthy fetch: give it a few
|
||||
// cycles (the engine rewrites rows mid-requeue) then stop.
|
||||
if (st == null && ++gone >= 3) break
|
||||
}
|
||||
setLive(d0.file.name, null)
|
||||
rescanStatuses()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue