Skip to content

perf: move AgentBootstrapService to Phase.Background and parallelize init#14096

Draft
DeJeune wants to merge 2 commits intov2from
DeJeune/agent-boot-perf
Draft

perf: move AgentBootstrapService to Phase.Background and parallelize init#14096
DeJeune wants to merge 2 commits intov2from
DeJeune/agent-boot-perf

Conversation

@DeJeune
Copy link
Copy Markdown
Collaborator

@DeJeune DeJeune commented Apr 7, 2026

What this PR does

Before this PR:
AgentBootstrapService ran in Phase.WhenReady with a sequential initialization chain (~4.4s), blocking other WhenReady services and delaying UI startup.

After this PR:

  • Moved to Phase.Background (fire-and-forget, never blocks other phases)
  • Removed unnecessary @DependsOn(['ApiServerService']) — none of the bootstrap operations use ApiServerService
  • Parallelized bootstrapBuiltinAgents, restoreSchedulers, and channelManager.start via Promise.all
  • Parallelized channel adapter connections in ChannelManager.start() (was sequential for...await)
image

Why we need it and why it was done in this way

The following tradeoffs were made:

  • All three bootstrap operations are idempotent, self-contained, and non-critical for UI rendering, so Phase.Background is the correct lifecycle phase per the Phase Selection Guide.

The following alternatives were considered:

  • Keeping Phase.WhenReady with manual fire-and-forget (this.initDone = Promise.all(...) without await) — rejected because it reimplements what Phase.Background already provides natively.
  • Parallelizing initCherryClaw and initCherryAssistant inside bootstrapBuiltinAgents — not done due to documented SQLITE_BUSY risk from concurrent writes.

Breaking changes

None. All changes are internal to the main process startup sequence.

Special notes for your reviewer

  • registerSessionStreamIpc() is synchronous (just registers ipcMain.handle calls) — no await needed.
  • ipcMain registration works in Phase.Background since it doesn't require Electron's app to be ready.
  • Channel adapters already handle their own errors in connectChannelFromRow, so Promise.all won't short-circuit on a single adapter failure.

Checklist

Release note

NONE

…init

AgentBootstrapService was blocking the WhenReady phase for ~4.4s with
sequential operations that have no UI-critical dependency. This change:

- Moves to Phase.Background (fire-and-forget, never blocks other phases)
- Removes unnecessary @dependsOn(['ApiServerService'])
- Parallelizes bootstrapBuiltinAgents, restoreSchedulers, and channelManager.start
- Parallelizes channel adapter connections in ChannelManager.start()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
@DeJeune DeJeune requested a review from a team April 7, 2026 12:24
Move registerSessionStreamIpc() from onReady() to onInit() to follow
the lifecycle convention: infrastructure setup in onInit, async work
in onReady.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
@DeJeune DeJeune marked this pull request as draft April 7, 2026 12:49
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