Lines 109-149javascript
109 prefetchingAccounts = new Set();
110 // Single-flight guard for syncAll. It's triggered from THREE places — boot,
111 // a 60s interval, and every visibilitychange→visible — with no coordination.
112 // On Android everything (incl. wa-sqlite) runs on the main thread, so
113 // overlapping runs stacked up: re-listing folders repeatedly, contending on
114 // the DB, and freezing the event loop ~1s at a time — the sync never
115 // advanced to fetching new mail, so the list stayed stale despite "Synced"
116 // (Bob 2026-06-27). Coalesce concurrent calls to one in-flight run.
117 syncAllInflight = null;
118 // Separate guard for the Phase-2/3 background pass (other folders + body
119 // prefetch). It runs DETACHED from the inbox guard so a long folder sweep
120 // can't make the 60s poll skip the inbox refresh (new mail must keep
121 // flowing). One background pass at a time — overlapping triggers no-op.
122 bgSyncInflight = null;
123 constructor(db, bodyStore) {
125 this.bodyStore = bodyStore;
127 on(_event, _handler) { }
128 emit(event, ...args) { emitEvent({ type: event, ...args[0] }); }
129 async addAccount(account) {
130 vlog(`addAccount id=${account.id} email=${account.email} host=${account.imap?.host} auth=${account.imap?.auth}`);
131 this.db.upsertAccount(account.id, account.name, account.email, JSON.stringify(account));
HighAi Review Evidence
The same remote logging runs during account registration and periodic mailbox activity.
android-bootstrap.jsView on unpkg · L129 132 // Idempotent: a provider already registered for this account is kept
133 // as-is. The Android bootstrap re-runs the account load periodically;
134 // recreating the provider each time built a fresh ImapWebProvider +
135 // BridgeTransport and replaced the live one — which orphaned any
136 // body fetch in flight on the old provider, so `fetchOne` came back
137 // with no source and the message showed "Body parsed empty". A real
138 // config change is rare and handled by a restart.
139 if (this.providers.has(account.id)) {
140 vlog(`addAccount ${account.id}: provider already registered — keeping it`);
143 if (this.isGmailAccount(account)) {
144 const tokenProvider = this.tokenProviders.get(account.id);
146 this.providers.set(account.id, new GmailApiWebProvider(tokenProvider));
147 console.log(`[sync] ${account.id}: Gmail API provider registered`);