# Fix Git ref refresh resource storms · PR \#4727 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/4727)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: t3code/git-ref-refresh-resource-storm

Target branch: main

Head commit: 2c4c29ca4c1909ff5610c175714d3830e647bf34

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/4727)

[Commits](https://git.cafe/pingdotgg/t3code/pull/4727/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/4727/diffs?format=markdown)

## Description

---

## What changed

- remove the five-second client-side ref polling loop and refresh once per connection generation
- expire idle ref atoms after 30 seconds
- key repository/ref snapshots by the common Git directory
- coalesce duplicate refreshes, single-flight full scans, and bound Git subprocess concurrency
- replace separate local/remote ref enumeration with one `for-each-ref` call
- invalidate cached snapshots after ref mutations

## Root cause

Each retained `vcs.listRefs` atom polled independently. On this repository that multiplied 31 concurrent requests into repeated full scans across 838 worktrees and roughly 16,700 refs. The server had no shared snapshot, single-flight guard, or concurrency bound, so identical requests launched many expensive `git branch`, `git worktree list`, and ref-enumeration processes at once.

## Impact

Ref lists remain fresh on connection changes and explicit refreshes, while background idle work no longer creates a Git subprocess storm. Mutations still invalidate snapshots immediately.

## Verification

- 34 focused client/server tests
- targeted formatting, lint, and affected-package typechecks
- integrated web verification: at most two expensive Git children and one worktree scan
- integrated mobile idle verification: zero expensive Git samples across 60 settled samples

Co-authored-by: codex <codex@users.noreply.github.com>

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Fix Git ref refresh resource storms with coalesced snapshots, exponential backoff, and invalidation hooks
> - Replaces periodic polling for VCS refs with a single refresh per connection generation, retried on failure using exponential backoff (1s base, 30s cap), and a 30s idle TTL instead of 5 minutes.
> - Adds a coalesced, cached `listRefs` snapshot in `GitVcsDriverCore` so concurrent paginated calls share one underlying `for-each-ref` scan, with generation tracking to prevent stale cache reuse.
> - Invalidates cached VCS refs (both in-memory and persisted) after any ref-affecting mutation (pull, push, createRef, switchRef, worktree ops, publish, etc.) on both success and failure via new `onSettled` hooks on RPC commands.
> - Adds `removeVcsRefs` and `clearVcsRefs` to `EnvironmentCacheStore` (web IndexedDB, mobile SQLite) and a per-environment persistence lock to serialize cache mutations.
> - Fixes branch list pagination in `BranchToolbarBranchSelector` to only trigger next-page loads on downward scroll past a threshold, not on layout or array length changes.
> - Risk: Idle `list-refs` atoms now expire after 30s instead of 5 minutes, causing more frequent re-fetches when the atom is re-subscribed after a period of inactivity.
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 2c4c29c.</sup>
> <!-- Macroscope's review summary ends here -->
>
> <!-- macroscope-ui-refresh -->
<!-- Macroscope's pull request summary ends here -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Large changes to GitVcsDriverCore caching, invalidation, and client ref streams affect branch lists and worktree-heavy repos; behavior is heavily tested but touches core VCS paths.
> 
> **Overview**
> Stops Git ref refresh from spawning subprocess storms by replacing per-atom 5s polling with **one refresh per connection generation** (exponential retry, 30s idle atom TTL) and a **server-side coalesced snapshot** keyed by common Git dir (`for-each-ref` + worktree metadata instead of separate branch listings).
> 
> **Invalidation:** VCS mutations (pull, worktree, create/switch ref, publish, stacked actions) clear persisted `vcs-refs` via new `clearVcsRefs` / `removeVcsRefs` on web and mobile stores, bump a per-environment revision, and invalidate server snapshots after Git-changing RPCs; `listRefs` accepts optional `refresh: true` (e.g. PR local branch lookup).
> 
> **UI:** Branch picker pagination loads the next page only on **downward scroll** near the bottom, with a dedicated `isFetchingNextPage` flag so background refreshes are not shown as “loading more.”
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 2c4c29ca4c1909ff5610c175714d3830e647bf34. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
