mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
fix: prevent IDB write-stall from blocking trip page and sync loop
clearAll() now clears all tables in a transaction instead of calling offlineDb.delete(), which triggered our versionchange handler and put Dexie into a broken write state for the rest of the session. tripRepo.get() gets the same 2 s timeout guard as list() so a stalled IDB read no longer freezes the trip splash screen. _doSync wraps each syncTrip() in a 30 s per-trip timeout so a single stalled write transaction cannot prevent the loop from advancing to subsequent trips.
This commit is contained in:
@@ -199,7 +199,46 @@ export async function clearBlobCache(): Promise<void> {
|
||||
|
||||
/** Wipe the entire offline database (called on logout). */
|
||||
export async function clearAll(): Promise<void> {
|
||||
await offlineDb.delete();
|
||||
// Re-open so subsequent operations don't fail
|
||||
await offlineDb.open();
|
||||
// Use table.clear() instead of offlineDb.delete() to avoid triggering the
|
||||
// versionchange handler (which calls close()), which would put Dexie into a
|
||||
// broken write state for the remainder of the session.
|
||||
await offlineDb.transaction(
|
||||
'rw',
|
||||
[
|
||||
offlineDb.trips,
|
||||
offlineDb.days,
|
||||
offlineDb.places,
|
||||
offlineDb.packingItems,
|
||||
offlineDb.todoItems,
|
||||
offlineDb.budgetItems,
|
||||
offlineDb.reservations,
|
||||
offlineDb.tripFiles,
|
||||
offlineDb.accommodations,
|
||||
offlineDb.tripMembers,
|
||||
offlineDb.tags,
|
||||
offlineDb.categories,
|
||||
offlineDb.mutationQueue,
|
||||
offlineDb.syncMeta,
|
||||
offlineDb.blobCache,
|
||||
],
|
||||
async () => {
|
||||
await Promise.all([
|
||||
offlineDb.trips.clear(),
|
||||
offlineDb.days.clear(),
|
||||
offlineDb.places.clear(),
|
||||
offlineDb.packingItems.clear(),
|
||||
offlineDb.todoItems.clear(),
|
||||
offlineDb.budgetItems.clear(),
|
||||
offlineDb.reservations.clear(),
|
||||
offlineDb.tripFiles.clear(),
|
||||
offlineDb.accommodations.clear(),
|
||||
offlineDb.tripMembers.clear(),
|
||||
offlineDb.tags.clear(),
|
||||
offlineDb.categories.clear(),
|
||||
offlineDb.mutationQueue.clear(),
|
||||
offlineDb.syncMeta.clear(),
|
||||
offlineDb.blobCache.clear(),
|
||||
])
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,10 @@ export const tripRepo = {
|
||||
},
|
||||
|
||||
async get(tripId: number | string): Promise<{ trip: Trip; refresh: TripRefresh }> {
|
||||
const cached = await offlineDb.trips.get(Number(tripId))
|
||||
const cached = await Promise.race([
|
||||
offlineDb.trips.get(Number(tripId)).catch(() => undefined),
|
||||
new Promise<undefined>(resolve => setTimeout(() => resolve(undefined), 2000)),
|
||||
])
|
||||
|
||||
const refresh: TripRefresh = (async () => {
|
||||
try {
|
||||
|
||||
@@ -195,7 +195,12 @@ export const tripSyncManager = {
|
||||
onProgress?.({ phase: 'trip', tripId: trip.id, index: i, total: toSync.length })
|
||||
let tripOk = false
|
||||
try {
|
||||
await syncTrip(trip.id)
|
||||
await Promise.race([
|
||||
syncTrip(trip.id),
|
||||
new Promise<never>((_, reject) =>
|
||||
setTimeout(() => reject(new Error('syncTrip timeout')), 30_000)
|
||||
),
|
||||
])
|
||||
tripOk = true
|
||||
} catch (err) {
|
||||
if (isQuotaError(err)) {
|
||||
|
||||
Reference in New Issue
Block a user