fix(app): IDB invalid state error on mobile safari (#8)

This commit is contained in:
hampus-fluxer 2026-01-03 14:55:09 +01:00 committed by GitHub
parent 84b6bb2a5b
commit 75f9afc843
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -325,6 +325,15 @@ class AccountStorage {
return name === 'DataCloneError'; return name === 'DataCloneError';
} }
private isInvalidStateError(error: unknown): boolean {
if (!error || typeof error !== 'object') {
return false;
}
const name = (error as {name?: unknown}).name;
return name === 'InvalidStateError';
}
async stashAccountData( async stashAccountData(
userId: string, userId: string,
token: string | null, token: string | null,
@ -388,6 +397,13 @@ class AccountStorage {
return; return;
} }
if (this.isInvalidStateError(err)) {
logger.warn(`InvalidStateError (database closing) while stashing account ${userId}; using memory store`, err);
this.memoryStore.set(userId, safeRecord);
logger.debug(`Stashed account data for ${userId} (memory fallback after InvalidStateError)`);
return;
}
logger.error(`Failed to stash account data for ${userId}`, err); logger.error(`Failed to stash account data for ${userId}`, err);
throw err; throw err;
} }
@ -523,6 +539,7 @@ class AccountStorage {
return this.memoryStore.get(userId) ?? null; return this.memoryStore.get(userId) ?? null;
} }
try {
return await withTimeout( return await withTimeout(
new Promise<StoredAccount | null>((resolve, reject) => { new Promise<StoredAccount | null>((resolve, reject) => {
const tx = this.db!.transaction([STORE_NAME], 'readonly'); const tx = this.db!.transaction([STORE_NAME], 'readonly');
@ -534,6 +551,14 @@ class AccountStorage {
5000, 5000,
'IndexedDB get account', 'IndexedDB get account',
); );
} catch (err) {
if (this.isInvalidStateError(err)) {
logger.warn(`InvalidStateError (database closing) in getRecord for ${userId}; using memory store`, err);
return this.memoryStore.get(userId) ?? null;
}
throw err;
}
} }
private async putRecord(record: StoredAccount): Promise<void> { private async putRecord(record: StoredAccount): Promise<void> {
@ -544,6 +569,7 @@ class AccountStorage {
return; return;
} }
try {
await withTimeout( await withTimeout(
new Promise<void>((resolve, reject) => { new Promise<void>((resolve, reject) => {
const tx = this.db!.transaction([STORE_NAME], 'readwrite'); const tx = this.db!.transaction([STORE_NAME], 'readwrite');
@ -557,6 +583,15 @@ class AccountStorage {
); );
this.memoryStore.set(record.userId, normalized); this.memoryStore.set(record.userId, normalized);
} catch (err) {
if (this.isInvalidStateError(err)) {
logger.warn(`InvalidStateError (database closing) in putRecord for ${record.userId}; using memory store`, err);
this.memoryStore.set(record.userId, normalized);
return;
}
throw err;
}
} }
private async updateLastActive(userId: string): Promise<void> { private async updateLastActive(userId: string): Promise<void> {