feat(dashboard): make the 30s auto-refresh ingest new usage (revives #59) - #157
Open
Lyazid21 wants to merge 1 commit into
Open
feat(dashboard): make the 30s auto-refresh ingest new usage (revives #59)#157Lyazid21 wants to merge 1 commit into
Lyazid21 wants to merge 1 commit into
Conversation
The auto-refresh timer only re-fetched /api/data — a pure read of usage.db — so with the dashboard open, fresh usage never appeared: nothing re-scans the transcript JSONL after the single startup scan, and users had to click Rescan or restart the server (the exact limitation noted in the phuryn#138 discussion). - The 30s timer now fires autoRefreshTick(), which POSTs /api/rescan (the same incremental, non-destructive scan as the button) before re-reading /api/data. An in-flight guard keeps ticks from stacking behind a slow scan; a guarded tick still re-reads, so a long scan renders progressively. - New module-level RESCAN_LOCK serializes scans server-side: a rescan arriving while one runs answers {"busy": true} without scanning, and the manual button reports "already scanning". cmd_dashboard's startup scan holds the same lock, so cold-start ticks skip instead of double-scanning the backlog. - SQLite lock waits raised 5s -> 30s on both paths (scanner.get_db connect timeout, dashboard read busy_timeout): scans now routinely run beside reads, and the end-of-scan sessions recompute can hold the write lock longer than 5s on a big DB. - Tests: /api/rescan busy path; template guards pinning the timer to autoRefreshTick and the scan-before-read order. Revives the intent of phuryn#59, which was closed while /api/rescan was still a destructive full rebuild — phuryn#138 (97e1d91, v1.2.6) made the endpoint incremental and append-only, which is what makes an auto-firing rescan safe now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With the dashboard open, fresh Claude Code usage never appears. The 30-second auto-refresh only re-fetches
/api/data, which is a pure read ofusage.db— nothing on the server re-scans the transcript JSONL after the single startup background scan. Users end up clicking ⟳ Rescan every time, or (more commonly, if they don't realize the button is the ingestion path) Ctrl+C-ing and relaunching the server. This is the limitation noted in the #138 discussion: "Auto-refresh only re-reads /api/data and never scans, so the button is the only in-session way to ingest new turns."Fix
autoRefreshTick(), which POSTs/api/rescan— the same incremental, non-destructive scan the button runs — and then re-reads/api/data. An in-flight guard keeps ticks from stacking behind a slow scan, and a guarded tick still re-reads, so a long scan renders progressively (preserving the serve-first/scan-behind cold-start behavior ofcmd_dashboard).RESCAN_LOCKserializes scans server-side: a rescan arriving while another runs (second tab, tick racing the manual button) gets an immediate{"busy": true}instead of a concurrent scan, andtriggerRescanshows "Rescan (already scanning)" for that case.cmd_dashboard's startup scan holds the same lock, so a tick during a cold start skips instead of double-scanning the backlog.scanner.get_dbconnect timeout, the dashboard's readbusy_timeout): scans now routinely run beside reads, and the end-of-scan sessions recompute can hold the write lock longer than 5s on a big DB./api/rescanbusy path, plus template guards pinning the timer toautoRefreshTick(never bareloadData) and the scan-before-read order inside the tick.Verification
HOME+CLAUDE_USAGE_DB, real server): turns appended to a session JSONL after startup were ingested by the tick'sPOST /api/rescanand reflected in/api/datawith exact token totals; the busy path returns{"busy": true}while the lock is held and resumes normally after.<script>blocks of the served page passnode --check.History
#59 proposed exactly this (auto-refresh running an incremental scan) back in April and was closed — understandably, since
/api/rescanwas a destructive full rebuild at the time, and auto-firing it would have been dangerous. #138 →97e1d91(v1.2.6) made the endpoint incremental and append-only, which is what makes an auto-firing rescan safe now. This PR revives #59's intent on that foundation.Notes
CHANGELOG.mddeliberately untouched (version headings accumulate onDEV); suggested bullet for the next section:sessionsrow (~0.8s measured at 500k turns). Scoping it to sessions touched by the scan would make active ticks O(delta).🤖 Generated with Claude Code