Skip to content

Fix long-thread database and event-loop stalls - #2025

Merged
ymichael merged 1 commit into
mainfrom
bb/investigate-bb-server-logs-thr_6mba4xzpa9
Aug 20, 2026
Merged

ymichael merged 1 commit into
mainfrom
bb/investigate-bb-server-logs-thr_6mba4xzpa9

Conversation

@ymichael

Copy link
Copy Markdown
Collaborator

What was wrong

Long-lived threads repeatedly scanned JSON payloads for todo tool names, rebuilt the full conversation outline for unrelated command and reasoning events, and pruned arbitrarily large sets of resolved deltas in one synchronous SQLite write. Those paths blocked the server event loop and delayed otherwise small event inserts. Separately, stall diagnostics attributed awaited RPC wall time as event-loop work, treated laptop suspension as a runtime stall, and warned on fresh 512-event bursts before there was evidence that delivery was stuck.

What changed

  • Add a guarded generated tool-name column and partial todo lookup index through Drizzle migration 0104.
  • Key the conversation-outline cache by the latest outline-relevant event while still returning the current thread sequence.
  • Use the materialized parent-tool-call column in remaining event queries and cap each resolved-delta prune pass at 500 rows.
  • Attribute event-loop stalls only to completed synchronous work; keep awaited routes visible only as current work.
  • Reset server and host event-loop samples after likely system suspension and report the host heartbeat wake as informational.
  • Require a depth-512 daemon event queue to remain queued for five seconds before warning, while retaining the unconditional thirty-second age warning.

The timeline byte limit and default event budget are intentionally unchanged. There are no server/host wire changes, so HOST_DAEMON_PROTOCOL_VERSION is unchanged.

How you verified

  • pnpm exec turbo run test --filter=@bb/db --force: 406 tests passed.
  • pnpm exec turbo run test --filter=@bb/host-daemon --force: 586 tests passed.
  • Affected server suites: 91 current tests passed, including outline caching, event-loop attribution, and timeline-window regression coverage.
  • pnpm exec turbo run test --filter=@bb/config --filter=@bb/domain --force: 108 config and 137 domain tests passed.
  • Affected app tests passed: 43 tests.
  • pnpm exec turbo run typecheck for @bb/db, @bb/domain, @bb/config, @bb/host-daemon, @bb/server, and @bb/app: all passed.
  • Reproduced the todo lookup on a copied 41k-event thread: median 11.46ms to 0.04ms. Reproduced a 5k-delta prune: median 10.05ms to 1.22ms per bounded pass.

The full server suite was also attempted, but existing npm-artifact packaging tests do not produce a clean signal in this sandbox; all suites covering changed server paths passed.

Fixes: N/A — log-driven performance investigation.

AGENT GENERATED: by GPT-5

@ymichael
ymichael merged commit 2ff5828 into main Aug 20, 2026
13 checks passed
@ymichael
ymichael deleted the bb/investigate-bb-server-logs-thr_6mba4xzpa9 branch August 20, 2026 08:47
ymichael added a commit that referenced this pull request Aug 20, 2026
## What was wrong

The active thread timeline and the full-history conversation outline
shared the same realtime invalidation group, so every events-appended
streaming batch sent another /conversation-outline request. The server
cache hardening now on main from #2025 avoids rebuilding for
outline-irrelevant events, but the client still performs redundant HTTP
reads at streaming cadence, and assistant text deltas can still
invalidate the full projection. The outline does not need sub-second
route refreshes because the incremental timeline already carries the
live conversation rows.

## What changed

- Split realtime timeline-window invalidation from conversation-outline
invalidation.
- Refresh the full outline at the terminal turn boundary instead of for
every streaming delta; unknown lifecycle notifications still invalidate
it conservatively, and history rewrites retain the existing full
invalidation path.
- Overlay live timeline conversation rows onto the cached full outline
so current user and assistant messages remain fresh while a turn
streams.
- Reconciled the server cache documentation with the outline-aware cache
added by #2025 and the new client refresh policy.
- Added regressions proving streaming deltas do not refetch the outline,
turn completion does, and live timeline labels replace or extend a
cached outline.

This implements the client-side pacing direction from #1972 using a turn
boundary plus live-row overlay instead of a timed debounce. It does not
change the API contract or the server/daemon wire format, so
HOST_DAEMON_PROTOCOL_VERSION is unchanged.

## How you verified

The new realtime invalidation test fails before the change because an
assistant delta refetches the active outline query. The TOC merge test
also fails before the change because a loaded outline always wins over
newer timeline rows.

After rebasing onto origin/main at 0b2723a:

- pnpm exec turbo run test --filter=@bb/app --
src/hooks/cache-owners/cache-owner-registry.test.ts
src/hooks/realtime-cache-effects.test.ts
src/components/thread/toc/ThreadTableOfContents.test.tsx — 80 tests
passed
- pnpm exec turbo run typecheck --filter=@bb/app — passed
- git diff --check origin/main...HEAD — passed

Fixes #1972

> AGENT GENERATED: by GPT-5
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