mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-30 18:46:00 +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). */
|
/** Wipe the entire offline database (called on logout). */
|
||||||
export async function clearAll(): Promise<void> {
|
export async function clearAll(): Promise<void> {
|
||||||
await offlineDb.delete();
|
// Use table.clear() instead of offlineDb.delete() to avoid triggering the
|
||||||
// Re-open so subsequent operations don't fail
|
// versionchange handler (which calls close()), which would put Dexie into a
|
||||||
await offlineDb.open();
|
// 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 }> {
|
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 () => {
|
const refresh: TripRefresh = (async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -195,7 +195,12 @@ export const tripSyncManager = {
|
|||||||
onProgress?.({ phase: 'trip', tripId: trip.id, index: i, total: toSync.length })
|
onProgress?.({ phase: 'trip', tripId: trip.id, index: i, total: toSync.length })
|
||||||
let tripOk = false
|
let tripOk = false
|
||||||
try {
|
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
|
tripOk = true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isQuotaError(err)) {
|
if (isQuotaError(err)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user