Description
Describe the bug
Hi, I've recently faced with an online issue whereby a small percentage (~1%) of my users are stuck in a loading screen (which I render when isRestoring is true).
I've got an alarm regarding JSErrors spiking, mostly coming from "Can't find variable: IndexedDB" and "Unable to open database file on disk".
I peeked at the source code and convinced myself its fine due to the finally block eventually setting isRestoring to false.
However I was looking at main branch instead of the version my project was relying on... (sad day :( )
main branch
persistQueryClientRestore(options)
.then(() => refs.current.onSuccess?.())
.catch(() => refs.current.onError?.())
.finally(() => {
setIsRestoring(false)
})
My project relies on v5.18.1, whose code snippet looks like this
v5.18.1
persistQueryClientRestore(options).then(async () => {
try {
await refs.current.onSuccess?.()
} finally {
setIsRestoring(false)
}
})
The configuration I have setup is this:
import { get, set, del } from 'idb-keyval'
import {
PersistedClient,
Persister,
} from '@tanstack/react-query-persist-client'
/**
* Creates an Indexed DB persister
* @see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
*/
export function createIDBPersister(idbValidKey: IDBValidKey) {
return {
persistClient: (client: PersistedClient) => set(idbValidKey, client),
restoreClient: () => get<PersistedClient>(idbValidKey),
removeClient: () => del(idbValidKey),
} satisfies Persister;
}
I was able to hotfix the problem by straight up removing isRestoring + persisterOptions.
I've spent the past 2 days staring at the source code of PersistQueryProvider and possibly found a scenario where isRestoring is never set back to false.
Even though v5.76.2 solves this, I'd argue that async persist storage should come with a timeout, (perhaps set to 5000ms) when restoring/persisting.
Historically at our scale we've encountered async processes never terminating before, which could replicate the above issue (isRestoring never false).
Let me know whether you guys agree with adding a timeout for async persistance, I can raise a PR + unit tests for it
Your minimal, reproducible example
https://codesandbox.io/p/sandbox/async-storage-restoring-hung-vlx2xj
Steps to reproduce
- Use PersistQueryClientProvider with IDB from document https://tanstack.com/query/latest/docs/framework/react/plugins/persistQueryClient#building-a-persister
- removeClient throw a synchronous error
- isRestoring is always true
Expected behavior
As a user, i expect isRestoring to be set to false if any of the Persister method fails (persistClient, restoreClient, removeClient)
Platform
- Android, iOS. More prevalent on iOS
- Replicable on Chrome
Tanstack Query adapter
react-query
TanStack Query version
v5.18.1
TypeScript version
v5.3.3