Skip to content

Prefetch timeline, queue, and approvals with thread bootstrap - #3

Merged
Guitaraholic merged 2 commits into
mainfrom
fix/thread-open-prefetch
Sep 2, 2026
Merged

Prefetch timeline, queue, and approvals with thread bootstrap#3
Guitaraholic merged 2 commits into
mainfrom
fix/thread-open-prefetch

Conversation

@Guitaraholic

@Guitaraholic Guitaraholic commented Sep 2, 2026

Copy link
Copy Markdown

Human comments

What was wrong

Opening a thread waited for GET /threads/:id?include=environment,host to settle, then started timeline, queued messages, and pending interactions. First paint of the thread chrome paid a serial waterfall. Related: get-bb/bb#1303 (~19 requests on open).

This is apps/app (web and Electron). The daemon already serves those three reads; the client just started them too late.

What changed

  • useThreadDetailBootstrap still returns the same bootstrap GET.
  • In the same turn it prefetchQuerys timeline, queued messages, and pending interactions, so React Query joins in-flight work instead of waiting for bootstrap to settle.
  • Removed the optional timelinePrefetch flag. AppLayout no longer has to opt in; ThreadDetailView gets the same start.

Wire shape is unchanged. This is not a GET /threads/:id/open payload. No HOST_DAEMON_PROTOCOL_VERSION bump.

Why this way

T3’s rule is: do less work before the thread view can paint. Collapsing everything into one subscribe payload (GET /threads/:id/open) is the later cut — new wire, enrolled daemons would need an update.

This PR only kills the waterfall we already own on the client: three reads that do not need environment can start immediately. Git work-status and pull-request reads still need environment, so they stay after bootstrap. Bundling those into bootstrap would either over-fetch or invent the one-payload API we are not shipping here.

Benefit to bb

Every thread open, web and desktop. Timeline, queue, and approvals start in the same turn as the include GET, so the thread view can paint chrome and fill the list from in-flight requests instead of a second serial round. Existing daemons keep working.

Already opened upstream: get-bb/bb#2935.

Harvest

Independent. Already on get-bb. Pairs with Datahazed #6 (paint from cache) and #7/#8 (start bootstrap earlier) but none of those are required for this PR to be correct.

Decision record: docs/perf-control-plane.md (PR #9).

How you verified

Phase-order test (apps/app/src/test/perf-phase.ts) records sidecar-reads-started while the include GET is still pending, then requires that mark to precede bootstrap-settled. Reverting to a waterfall fails this test.

  • apps/app/src/hooks/queries/thread-queries.test.tsx asserts timeline, queued messages, and pending interactions are requested before bootstrap settles. 22 passed.

Related: get-bb#1303, get-bb#2935

AGENT GENERATED

Opening a thread waited for GET /threads/:id before starting the
payloads the view needs next. Start those reads in the same turn so
React Query joins in-flight work instead of a second serial round.

Fixes get-bb#1303
…ttles.

Phase log records sidecar-reads-started while the include GET is still
pending, then requires that mark to precede bootstrap-settled.
@Guitaraholic
Guitaraholic merged commit bae5752 into main Sep 2, 2026
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