fix: stop live check view from reload-looping when result is stale
commit
e5e8780fix: stop live check view from reload-looping when result is stale
The poller signalled done whenever the in-memory live buffer was gone, even if the persisted result still read queued/running (the worker had not caught up yet). The reloaded page picked the live view again and polled straight back into done, reloading forever. Add a stale state that reports the mismatch without reloading.
Assisted-by: Claude:claude-sonnet-5
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
crates/git-ents-server/src/web/live.js
@@ -3,14 +3,21 @@
const poll = () => {
fetch(url, { cache: 'no-store' })
.then((response) => {
- if (response.headers.get('X-Check-Live') === 'done') {
- window.location.reload();
- return null;
- }
- return response.text();
+ const state = response.headers.get('X-Check-Live');
+ return response.text().then((html) => ({ state, html }));
})
- .then((html) => {
- if (html === null) return;
+ .then(({ state, html }) => {
+ if (state === 'done') {
+ window.location.reload();
+ return;
+ }
+ if (state === 'stale') {
+ container.insertAdjacentHTML(
+ 'beforeend',
+ '<p class="shell-note">No live output available right now; this check is still marked in progress.</p>'
+ );
+ return;
+ }
container.innerHTML = html;
setTimeout(poll, 1000);
})
crates/git-ents-server/src/web/pages.rs
@@ -1064,11 +1064,14 @@
}
/// One poll of a running check's live output — the fragment [`LIVE_SCRIPT`]
-/// swaps into the run page's `#live-terminal` container. Signals completion
-/// (the check no longer has a live buffer: it settled, or was never queued)
-/// via the `X-Check-Live: done` response header rather than the body, so the
-/// script can tell a finished check apart from one that simply has no output
-/// yet.
+/// swaps into the run page's `#live-terminal` container. Reports its state via
+/// the `X-Check-Live` response header rather than the body, so the script can
+/// tell the three cases apart: `running` (a live buffer exists), `done` (no
+/// live buffer, and the persisted result has actually settled), or `stale` (no
+/// live buffer, but the persisted result still reads queued/running — the
+/// worker hasn't caught up yet). Reporting `done` in the `stale` case is what
+/// used to send the script into a reload loop, since the reloaded page would
+/// still pick the live branch and poll straight back into "done".
///
/// [`LIVE_SCRIPT`]: super::assets::LIVE_SCRIPT
pub(super) async fn check_live_fragment(
@@ -1082,9 +1085,15 @@
};
let key = (repo.to_owned(), commit_oid, name.to_owned());
let recording = git_effect::engine::live_snapshot(live_runs, &key);
- let done = recording.is_none();
+ let header = if recording.is_some() {
+ "running"
+ } else {
+ match latest_outcome(repo, commit_oid, name).await {
+ Some(outcome) if super::render::is_in_progress(outcome.status) => "stale",
+ _ => "done",
+ }
+ };
let body = super::render::live_fragment_body(recording).into_string();
- let header = if done { "done" } else { "running" };
([("x-check-live", header)], body).into_response()
}