fix(dashboard): atomic, non-fatal statusline writes - #116
Conversation
The dashboard could crash on startup with `ENOENT: rename …/tmux-statusline/…txt.tmp → …txt` (surfaced confusingly as `failed to spawn "undefined"` in dashboard mode). Root cause: rewriteLocalStatuslineArtifacts hand-rolled a write using a single shared `<file>.tmp` path, so concurrent clients/refreshes raced — one renamed the other's temp file out from under it. - statusline writes now go through writeTextAtomic (unique per-write temp name + mkdir + fsync) and are wrapped so a write failure logs and is ignored rather than aborting dashboard startup — statusline is cosmetic tmux chrome and must never take the dashboard down - the top-level catch no longer reports `failed to spawn "undefined"` when there is no tool; dashboard-mode failures now say "dashboard failed to start" - test: 50 concurrent writers to one path never ENOENT, leave a valid result, and litter no temp files Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThree statusline file-writing call sites in ChangesAtomic write migration for statusline files
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Follow-up to the same race: the daemon/dashboard runtime had two more hand-rolled shared-".tmp" statusline writers (the ones that actually produced the observed bottom-dashboard-<client>.txt crash), plus the statusline.json snapshot write: - dashboard-control.ts writeStatuslineTextFile (primeLiveTmuxFooter) - persistence-methods.ts writeStatuslineTextFile (precompute path) - persistence-methods.ts statusline.json snapshot All now go through writeTextAtomic (unique temp + mkdir + fsync); the text writers are wrapped so a failure logs and is ignored rather than crashing. statusline.json keeps its compact JSON via writeTextAtomic (not the pretty writeJsonAtomic). Test reworked to deterministically prove the unique-temp property: occupying the shared "<file>.tmp" path as a directory fails the old fixed-".tmp" writer but not the unique-temp one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem
The dashboard could crash on startup with:
Two defects:
rewriteLocalStatuslineArtifacts(src/main.ts) hand-rolled an "atomic" write using a single shared<file>.tmppath. When more than one client/refresh writes the same statusline file concurrently, they collide on that temp path and one renames the other's temp out from under it →ENOENTon rename. A cosmetic statusline write then took down the whole dashboard.toolisundefined, so the top-level catch printedfailed to spawn "undefined"for what was really a dashboard-startup error.Fix
writeTextAtomic(unique per-write temp name +mkdir -p+ fsync) instead of a shared.tmp, and are wrapped in try/catch so a write failure is logged and ignored — statusline is cosmetic tmux chrome and must never abort dashboard startup.dashboard failed to startwhen there is no tool, instead offailed to spawn "undefined".Test
atomic-write.test.ts: 50 concurrent writers to one path neverENOENT, leave a valid final value, and litter no temp files.yarn typecheck/lint/build/ fullvitest(1115) all pass.🤖 Generated with Claude Code
Summary by CodeRabbit
Tests
Bug Fixes