Skip to content

fix(pi-fff): non-blocking session_start warmup - #599

Open
gustav-fff wants to merge 1 commit into
mainfrom
triage-bot/issue-477
Open

fix(pi-fff): non-blocking session_start warmup#599
gustav-fff wants to merge 1 commit into
mainfrom
triage-bot/issue-477

Conversation

@gustav-fff

Copy link
Copy Markdown
Collaborator

Closes #477

Root cause

packages/pi-fff/src/index.ts session_start handler awaited ensureFinder()finder.waitForScan(15000). Pi recreates the session runtime on /new and /resume, so the lifecycle hook blocked the UI until the FFF initial scan finished (up to 15s on large workspaces).

Fix

  • Schedule ensureFinder(activeCwd) from session_start via setTimeout(0) instead of awaiting it. The handler returns immediately; the warmup runs in the background.
  • Track a monotonic lifecycleId, bumped on every session_start and session_shutdown. The deferred warmup checks the captured id and bails out (no ensureFinder, no ctx.ui.notify) if the session has been replaced.
  • ensureFinder returns the local created handle instead of the mutable finder global, so a destroyFinder() racing the warmup cannot hand back a destroyed/replaced instance to the caller.

The native SDK already exposes waitForScan as a non-blocking polling loop (packages/fff-node/src/finder.ts:477), so no SDK changes were needed — only the lifecycle hook.

Steps to reproduce

Pre-fix, on main:

git checkout main
cd packages/pi-fff
# Run pi with the extension installed against a large workspace (e.g. chromium / linux)
pi
# In pi: type /new and press Enter

Expected: new session is interactive immediately.
Actual (pre-fix): UI hangs for up to 15s while FileFinder.create + initial scan runs inside session_start. Same hang on /resume after picking a session.

Post-fix: /new and /resume return instantly. The first ffgrep / fffind / @-mention call awaits the same in-flight ensureFinder promise as before.

How verified

  • bun test test/ in packages/pi-fff — all 17 tests pass (test helper updated to flush the deferred warmup before asserting).
  • tsc --noEmit produces only the pre-existing module-resolution errors (unchanged from main).
  • Manual code review of the lifecycle race: shutdown during warmup is safe because the deferred callback short-circuits on stale lifecycleId, and ensureFinder returns the local handle.

Automated triage via Gustav. Honk-Honk 🪿

Schedule FileFinder.create + waitForScan via setTimeout(0) so Pi /new and
/resume return immediately. A monotonic lifecycleId tagged on each
session_start / session_shutdown lets a stale warmup detect that the
session has been replaced and skip both ensureFinder and ctx.ui.notify.
ensureFinder now returns the local handle so a shutdown mid-warmup can't
hand back a destroyed/replaced finder.

Closes #477
@kaushikgopal

Copy link
Copy Markdown

out of curiosity - any reason this hasn't been merged yet? would help my personal setup a lot (atm pi-fff alone accounts for 80% of my startup time).

screenshot_20260710_004173@2x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants