fix(web): survive page reload without losing analysis or running LLM jobs - #18
Conversation
…jobs The web UI kept repo, branch pair, analysis, and job ids only in React state, so a reload dropped everything while the server kept the jobs running. Persist the session and the active job list in sessionStorage (web only, per tab), re-run the analysis on load, and re-attach to stored job streams after probing that the server still knows them. A job is forgotten only on a terminal event; Chromium fires the EventSource error during page teardown, so cleaning up on error wiped the list before the new page loaded. Jobs are scoped to the repo they were started for, each stream closes only the EventSource it owns, and a stored session is ignored when the server's --repo changed. Refinement results read the current analysis through a ref instead of a stale closure, which also fixes cached refinements being dropped on the first analysis of a page; a live result wins over a cached one.
|
Should we store the refinment streaming in SQLite, then we could use:
Thoughts on the above? |
|
SQLite would make sense. I'll get to it soon enough |
refsPinned was seeded false on mount, so the effect that persists the session rewrote the stored pin to false on the first reload. Refs survived one reload via restoredRepo, then loadRepoInfo auto-detected over them on the next. Seed the ref from the restored session.
ActivityManager.jobs only ever grew: create_job inserted, nothing removed. Every job's history stayed resident for the life of the process, including Completed payloads carrying whole RefinementResults, and jobStreamAlive kept reporting long-dead jobs as live. Stamp finished_at on the terminal event and sweep finished jobs past JOB_RETENTION when a new job starts — no timer task, and if nothing is created nothing grows. Live jobs (no terminal event yet) always survive.
|
Went with SQLite's only real addition is surviving a backend restart, and if the server dies mid-refinement the LLM call dies with it The actual defect in that area was unbounded growth of Happy to revisit SQLite if resumable server-side jobs become the goal, since that's the problem it'd genuinely solve. |
Problem
In the web UI (
diffcore-web), a browser reload dropped everything: repo path, branch pair, analysis, and any LLM refinement / deep-analysis job that was still running. The server kept running the jobs and retained their SSE history, but the UI held all of that state only in React memory and never reconnected.Fix (web only, desktop opts out)
sessionStorage(per tab): repo path, base/head, the server's--repoit was recorded under, the repo the current analysis was run for, and whether the branch pair was picked explicitly.--repochanged, when the field holds an unsubmitted PR URL, or when the record is malformed.git checkoutmade in a terminal (the web UI has no HEAD watcher).errorwas wrong: Chromium fires theEventSourceerror during page teardown, which wiped the list before the new page loaded.EventSourceit owns.Preview
Verification
session-restore.spec.tscovers repo field + picked branches surviving reload, auto-detect resuming after changing the repo, and auto-detected branches being re-detected after reload.diffcore-webon this repo with real Claude CLI refinements (the demo-mode e2e suite has no server, so job reattach is manually verified only):--repo: field resets to the server's repo; unchanged: analysis restored without a click