Skip to content

fix(daemon): stop session flood and add session GC#1

Open
doyled-it wants to merge 1 commit into
mainfrom
fix/session-flood-and-gc
Open

fix(daemon): stop session flood and add session GC#1
doyled-it wants to merge 1 commit into
mainfrom
fix/session-flood-and-gc

Conversation

@doyled-it

Copy link
Copy Markdown
Owner

Problem

The session table grew without bound, spawning thousands of dashboard rows. Traced from a live ~/.wavecrest/state.db backup (62 MB / 3,346 sessions / 19,874 events). Two distinct defects:

  1. Indiscriminate adoption — every claude process that fired a SessionStart hook was adopted as a persistent session row, including headless claude -p one-shots and scripted bursts. One worktree produced 3,267 rows at ~28/min, each a short invocation that started and stopped with zero tool use (1 PreToolUse / 1 PostToolUse across all of them).
  2. No garbage collectionfinished sessions and their events were never pruned, and sessions whose process died without a SessionEnd hook lingered as idle/working zombies forever.

Fix

  • Defer wild adoption until a session shows real activity (first PreToolUse / PostToolUse). Start/stop-only invocations never create a row — this eliminates ~99% of the flood at the source. Planned (wavecrest-launched) sessions still bind on SessionStart, unchanged.
  • Hourly GC (src/daemon/gc.ts): reaps non-terminal sessions idle > 24h to finished (clears zombies), and deletes finished sessions older than 7 days (FK cascade clears events/rollup/samples). Pinned sessions are exempt from both.

Tests

  • New coverage for both GC queries, the GC pass, and the deferred-adoption contract.
  • 14 targeted tests pass (stable across repeated runs).
  • Full suite: 118 pass / 1 fail — the single failure (an SSE timeout in http.test.ts) is pre-existing and fails identically on main.
  • No new type errors introduced (gc.ts is type-clean).

Out of scope (noticed separately)

  • The usage-poller is failing to spawn its meta-claude (posix_spawnp failed, hundreds of consecutive failures) — opposite problem, worth a separate fix.

Two defects let the session table grow without bound:

- Indiscriminate adoption: every `claude` process that fired a SessionStart
  hook was adopted as a persistent dashboard row, including headless
  `claude -p` one-shots and scripted bursts. One worktree produced 3,267
  rows (~28/min) this way.
- No garbage collection: finished sessions and their events were never
  pruned, and sessions whose process died without a SessionEnd hook lingered
  as idle/working zombies forever.

Defer wild adoption until a session shows real activity (first PreToolUse /
PostToolUse), so start/stop-only invocations never create a row. Planned
(wavecrest-launched) sessions still bind on SessionStart, unchanged.

Add an hourly GC that reaps non-terminal sessions idle > 24h to 'finished'
and deletes finished sessions older than 7 days (FK cascade clears their
events/rollup/samples). Pinned sessions are exempt from both.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant