Skip to content

perf(mobile): cold starts feel faster and reconnect more quietly - #38

Draft
wSedlacek wants to merge 7 commits into
mainfrom
t3/improve-mobile-connection
Draft

wSedlacek wants to merge 7 commits into
mainfrom
t3/improve-mobile-connection

Conversation

@wSedlacek

Copy link
Copy Markdown

Reopened from closed upstream PR pingdotgg#32543 as a draft for t3.1code.
Idea rank: 37 of 108. Branch is as it was upstream; it likely needs a rebase (modernize) before review.

Summary

Depends on / stacked on pingdotgg/t3code#30835 (seamless resume: open the replacement before closing the old session). Merge that first; this layer sits on top.

Mobile sat on “Connecting to MacBook…” for a long time on launch and on resume, even when cached threads were already usable. Reconnect also retried dead paths, raced every saved machine at once, and waited for the full server-config snapshot before feeling connected.

This PR makes cold start and reconnect feel fast: quieter UI, less wasted work on the wire, and earlier transport readiness — without redoing pingdotgg#30835’s side-by-side replace.

What changed (this layer)

1. Remember the route that worked last
Successful connects move that route to the front for next time.

2. Hedge hanging routes
After ~250ms, open a backup in parallel. First ready wins; the loser closes. (Better-route upgrades stay serial so a backup cannot steal the preferred path.)

3. Quieter status over cached data
Cached threads keep a quiet “Updating…” header instead of a loud reconnect banner.

4. Skip LAN when you’re not on a private network
On mobile cellular, drop LAN unless it’s the only saved route.

5. Defer stale environments on cold start
Environments last reached ≥6 hours ago wait 2s so the recent machine gets the first sockets.

6. Warm T3 Connect credentials earlier
Prefetch DPoP tokens on cold start and on app wake / network change for recent T3 Connect environments.

7. Overlap the preferred relay ticket with route checks
Mint the preferred DPoP WebSocket ticket while LAN classification runs.

8. Skip the LAN head-start when no LAN remains
No ~500ms reachability window when the candidate list is remote-only.

9. Ready when the socket opens
session.ready no longer waits for the full server-config snapshot. The UI can leave “Connecting…” as soon as the WebSocket is up; config still arrives on initialConfig / subscriptions.

10. Empty-state loading while a sibling syncs
Home / new-task empty states keep loading when one environment is connected and another is still syncing, instead of flashing a hard failure.

From pingdotgg#30835 (do not re-review here)

Side-by-side session replace on resume and better-route upgrades — lands with that PR.

Tradeoffs (short)

Choice Upside Cost
Sticky last-good route Faster when the network matches last success Home Wi‑Fi may try Tailscale first until LAN wins again
Hedge after 250ms Dead preferred routes don’t serialize full timeouts Briefly more parallel connect work
Quiet “Updating…” Cached UI doesn’t feel blocked Less shouty reconnect chrome
Skip LAN on cellular No multi-second waits on 192.168.x.x Rare cellular→LAN reachability still skips LAN
6h / 2s deferral Recent machine wins cold start Env last used 7h ago waits 2s
Prefetch DPoP Cold T3 Connect hits cache more often Extra cloud/relay traffic for recent envs
Early ticket mint Relay prepare overlaps LAN checks Ticket discarded if a direct route wins
Ready before config Header clears as soon as the tunnel is up Features that need config still wait on serverConfig

Left alone on purpose

  • Always-connected iOS background (platform limit)
  • New tunnel protocols

Stack note

GitHub base stays main until fix/mobile-resume-race exists on pingdotgg/t3code (contributor branch is fork-only). History is based on pingdotgg#30835’s tip merged onto current main; the diff will shrink when pingdotgg#30835 merges. Maintainers can retarget --base fix/mobile-resume-race once that branch is on origin.

Test plan

  • Cold-launch mobile with a cached MacBook shell: threads show immediately; header says Updating… rather than Reconnecting to MacBook
  • Away from home after T3 Connect/Tailscale: next cold start prefers that route before a dead LAN
  • LAN answers then hangs: backup connects within the hedge window; no second live session left behind
  • On cellular with LAN + remote saved: does not sit on LAN; uses remote
  • Two enabled environments, one last connected >6h ago: recent starts first; stale ~2s later
  • Force-quit / reopen with T3 Connect: faster when token was warmed
  • Background the app over Tailscale/T3 Connect, kill the old socket, return: seamless replace from fix(client-runtime): connections switch without showing a reconnect pingdotgg/t3code#30835 still holds with this layer on top
  • Better LAN becomes reachable while on relay: upgrades beside the live session without a connecting flash
  • vp run check:changed

Created with Composer in Cursor (T3 Code).

🤖 Generated with Claude Code

levelorbit and others added 7 commits November 4, 2026 14:03
…ng the old session

The supervisor ended a session before it started the next one, on resume,
on network changes and on route upgrades. On a remote route a resume
waited out the 2.5 s silence window before any new connection began, and
every switch showed "Syncing threads…" even when the host was reachable.

Fixes pingdotgg#30833.
# Conflicts:
#	packages/client-runtime/src/connection/supervisor.test.ts
#	packages/client-runtime/src/connection/supervisor.ts
Sticky routes, hedged connects, quieter status, LAN skip, stale deferral,
DPoP prefetch, early ticket, ready-on-WS-open, wake renew, and relay
endpoint reuse — stacked on seamless resume from pingdotgg#30835.

Co-authored-by: Cursor <cursoragent@cursor.com>
Empty states were treating sibling sync errors as hard failures and
flashing the disconnected UI while another environment was still connecting.

Co-authored-by: Cursor <cursoragent@cursor.com>
Gate prefer-route persistence on a successful initialConfig so a socket that
opens to the wrong environment cannot stick for the next cold start. Treat
VPN/OTHER like UNKNOWN on mobile so Tailscale-on-Wi-Fi still keeps LAN routes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added vouch:trusted Author is trusted by repo permissions or the VOUCHED list. size:XXL labels Nov 14, 2026
@github-actions

Copy link
Copy Markdown

This PR changes the test suite by +32 test cases (browser 0, unit +32, server 0).

Keep tests that would fail for a real reason, and test logic below the UI where it can be. See Testing.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted Author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants