Skip to content

perf(mobile): pause the session-screen fallback poll while backgrounded - #9875

Merged
nwparker merged 1 commit into
mainfrom
nwparker/perf-mobile-session-poll-gate
Jul 22, 2026
Merged

nwparker merged 1 commit into
mainfrom
nwparker/perf-mobile-session-poll-gate

Conversation

@nwparker

@nwparker nwparker commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

What

The mobile session screen (session/[worktreeId].tsx) runs a fallback poll that sends both session.tabs.list AND terminal.list every 2 seconds while the route is focused. useFocusEffect stops it when you navigate away, but not when the app goes to background — so a connected phone in your pocket kept firing ~60 RPC/min (plus host work + a radio wakeup) on this screen.

This applies the same fix as #9857 (host screen): gate the 2s poll on AppState.currentState === 'active' and immediately reconcile both lists on foreground return.

  • The interval now calls a refreshOnForeground that returns early unless the app is active.
  • An AppState 'change' listener (attached before the immediate focus refresh, to cover the attach race) refetches both lists on return to 'active'.
  • Cleanup clears the interval and removes the listener.

The live session.tabs.subscribe subscription and the terminal streams are untouched — those carry live data with no polling replacement.

ELI5

When you had a terminal session open on your phone and put the phone away, it kept asking the computer "what tabs and terminals exist?" twice a second forever. Now it pauses that while the app is backgrounded and instantly catches up the moment you return. The live terminal output stream is never touched.

Proof of zero regression

  • Live subscriptions (session.tabs.subscribe, terminal streams) and existing in-flight / modal / optimistic-reconciliation behavior are preserved; only the fallback list poll is background-gated.
  • Foreground behavior is unchanged: on focus (which only happens while active) it still refreshes immediately, and the AppState listener guarantees an immediate refresh on any background→foreground transition, so the view is never stale on resume.
  • Verified in a deps-installed mobile checkout: pnpm typecheck clean, full mobile suite 2228 pass / 2 skipped (306 files), oxlint clean (screen stays within its frozen max-lines budget), oxfmt --check clean. Added test covers: early background return, both fetches while active, listener-before-refresh ordering, resume refresh, the 2s interval, and both cleanup paths.

Proof of perf improvement

While backgrounded this stops ~60 RPC/min (session.tabs.list + terminal.list) and the associated host work + radio wakeups on the session screen; the added test asserts the poll body returns without issuing either RPC while AppState !== 'active', and refetches on resume. Foreground steady-state keeps the exact 2s fallback cadence. Companion to #9857 (host screen).

Made with Orca 🐋

Co-authored-by: Orca <help@stably.ai>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Updated session polling to check for an active app state before fetching session tabs and terminals. The session screen now refreshes immediately when the app returns to the foreground, schedules guarded polling every two seconds, and removes the interval and app-state listener during cleanup. Added source-based tests covering foreground transitions, polling cadence, subscription registration, and teardown.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change well, but it does not follow the required template or include several required sections. Reformat the PR body to match the template and add Summary, Screenshots, Testing, AI Review Report, Security Audit, and Notes sections.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: pausing session-screen polling while backgrounded.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
mobile/src/session/mobile-session-startup-source.test.ts (1)

32-50: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Prefer behavioral coverage for the polling lifecycle.

This test only matches source strings, so it cannot detect runtime regressions in AppState gating, listener registration, interval behavior, or cleanup. Extract the polling lifecycle into a small testable helper (or add a runtime harness), and document why source-level testing is required here.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 99905198-2b76-4d1d-9652-2c9a37b92a49

📥 Commits

Reviewing files that changed from the base of the PR and between e600600 and f6eda4c.

📒 Files selected for processing (2)
  • mobile/app/h/[hostId]/session/[worktreeId].tsx
  • mobile/src/session/mobile-session-startup-source.test.ts

@nwparker
nwparker merged commit 76f5b83 into main Jul 22, 2026
3 checks passed
@nwparker
nwparker deleted the nwparker/perf-mobile-session-poll-gate branch July 22, 2026 21:13
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 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