Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/persister-await-storage-write.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/query-persist-client-core': patch
---

fix(query-persist-client-core/createPersister): await the storage write in `persistQuery`, so `persistQueryByKey` resolves only once the entry has actually been written and rejects when the write fails instead of leaving an unhandled rejection
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,64 @@ describe('createPersister', () => {
},
})
})

it('should not resolve until an asynchronous write has finished', async () => {
const storage = getFreshStorage()
let releaseWrite!: () => void
const writeGate = new Promise<void>((resolve) => {
releaseWrite = resolve
})
const { persister, client, queryKey, storageKey } = setupPersister(
['foo'],
{
storage: {
...storage,
setItem: async (key, value) => {
await writeGate
await storage.setItem(key, value)
},
},
},
)

client.setQueryData(queryKey, 'baz')

let settled = false
const persisted = persister
.persistQueryByKey(queryKey, client)
.then(() => {
settled = true
})

await vi.advanceTimersByTimeAsync(0)

expect(settled).toBe(false)
expect(await storage.getItem(storageKey)).toBeUndefined()

releaseWrite()
await persisted

expect(settled).toBe(true)
expect(JSON.parse(await storage.getItem(storageKey))).toMatchObject({
state: { data: 'baz' },
})
})

it('should reject when the write fails', async () => {
const storage = getFreshStorage()
const { persister, client, queryKey } = setupPersister(['foo'], {
storage: {
...storage,
setItem: () => Promise.reject(new Error('storage is full')),
},
})

client.setQueryData(queryKey, 'baz')

await expect(
persister.persistQueryByKey(queryKey, client),
).rejects.toThrow('storage is full')
})
})

describe('retrieveQuery', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/query-persist-client-core/src/createPersister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export function experimental_createQueryPersister<TStorageValue = string>({
async function persistQuery(query: Query) {
if (storage != null) {
const storageKey = `${prefix}-${query.queryHash}`
storage.setItem(
await storage.setItem(
storageKey,
await serialize({
state: query.state,
Expand Down