-
Notifications
You must be signed in to change notification settings - Fork 30
Open
Description
Problem
Every time the iOS app is cold-started (process killed by OS while backgrounded), users see a loading spinner for 1-3 seconds before sessions appear. This happens on every reopen because:
- Zustand store initializes with
isDataReady: falseand empty sessions SessionsListWrappershows a spinner whenuseSessionListViewData()returnsnull- The app must fetch
/v2/sessions, decrypt all session encryption keys (sequential loop), decrypt metadata + agentState per session, then callapplyReady()
Sessions are not persisted to MMKV — only drafts, permission modes, and settings are cached locally.
Root Cause Analysis
In sessionSnapshot.ts, both decryption loops are fully sequential (await inside for):
- Lines 75-90: Sequential encryption key decryption (
decryptEncryptionKeyper session) - Lines 95-149: Sequential session metadata/agentState decryption
In sync.ts:
applyReady()(the only placeisDataReadybecomestrue) is called in exactly one place:#init()line 527, aftersessionsSync.awaitQueue()+machinesSync.awaitQueue()completeisDataReadystarts asfalseand is never persisted
Proposed Fix
Phase 1: Parallelize decryption (low risk, high impact)
- Use
Promise.all(with concurrency limit) for the key decryption loop - Use
Promise.allfor the session metadata/agentState decryption loop
Phase 2: Cache session list to MMKV (medium risk, highest impact)
- After
applySessions(), serializesessionListViewDatato MMKV - On cold start, load cached data immediately before fetch completes (stale-while-revalidate)
- Set
isDataReady: trueimmediately if cache exists
Environment
- iOS (Happier mobile app)
- Affects all cold starts (any time iOS kills the app process in background)
- More noticeable with many sessions (50+)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels