Skip to content

Commit 67755ce

Browse files
authored
fix(scheduleGarbageCollection): Do not garbage collect newly cached queries of the same hash (#332)
* Add manual/prefetch cleanup test that fails * Prefetch both queries in second test * Add cleanup comment that will make the tests pass * Store when the GC was initiated and compare against updatedAt * Replace solution with state marker check and streamline test * Undo setting.json change * Undo setting.json change
1 parent 63f3d82 commit 67755ce

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

src/queryCache.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const queryCache = makeQueryCache()
1717
const actionInit = {}
1818
const actionFailed = {}
1919
const actionMarkStale = {}
20+
const actionMarkGC = {}
2021
const actionFetch = {}
2122
const actionSuccess = {}
2223
const actionError = {}
@@ -238,9 +239,12 @@ export function makeQueryCache() {
238239
}
239240

240241
query.scheduleGarbageCollection = () => {
242+
dispatch({ type: actionMarkGC })
241243
query.cacheTimeout = setTimeout(
242244
() => {
243-
cache.removeQueries(d => d.queryHash === query.queryHash)
245+
cache.removeQueries(
246+
d => d.state.markedForGarbageCollection && d.queryHash === query.queryHash
247+
)
244248
},
245249
typeof query.state.data === 'undefined' &&
246250
query.state.status !== 'error'
@@ -447,6 +451,7 @@ export function defaultQueryReducer(state, action) {
447451
canFetchMore: false,
448452
failureCount: 0,
449453
isStale: action.isStale,
454+
markedForGarbageCollection: false,
450455
data: action.initialData,
451456
updatedAt: action.hasInitialData ? Date.now() : 0,
452457
}
@@ -460,6 +465,12 @@ export function defaultQueryReducer(state, action) {
460465
...state,
461466
isStale: true,
462467
}
468+
case actionMarkGC: {
469+
return {
470+
...state,
471+
markedForGarbageCollection: true,
472+
}
473+
}
463474
case actionFetch:
464475
return {
465476
...state,

src/tests/queryCache.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,34 @@ describe('queryCache', () => {
143143
await sleep(50)
144144
expect(query.state.isStale).toBe(false)
145145
})
146+
147+
test('query is garbage collected when unsubscribed to', async () => {
148+
const queryKey = 'key'
149+
const fetchData = () => Promise.resolve('data')
150+
await queryCache.prefetchQuery(queryKey, fetchData, { cacheTime: 0 })
151+
const query = queryCache.getQuery(queryKey)
152+
expect(query.state.markedForGarbageCollection).toBe(false)
153+
const unsubscribe = query.subscribe(1)
154+
unsubscribe()
155+
expect(query.state.markedForGarbageCollection).toBe(true)
156+
await sleep(1)
157+
expect(queryCache.getQuery(queryKey)).toBeUndefined()
158+
})
159+
160+
test('query is not garbage collected unless markedForGarbageCollection is true', async () => {
161+
const queryKey = 'key'
162+
const fetchData = () => Promise.resolve(undefined)
163+
await queryCache.prefetchQuery(queryKey, fetchData, { cacheTime: 0 })
164+
const query = queryCache.getQuery(queryKey)
165+
expect(query.state.markedForGarbageCollection).toBe(false)
166+
const unsubscribe = query.subscribe(1)
167+
unsubscribe()
168+
expect(query.state.markedForGarbageCollection).toBe(true)
169+
queryCache.clear()
170+
queryCache.setQueryData(queryKey, 'data')
171+
await sleep(1)
172+
const newQuery = queryCache.getQuery(queryKey)
173+
expect(newQuery.state.markedForGarbageCollection).toBe(false)
174+
expect(newQuery.state.data).toBe('data')
175+
})
146176
})

src/tests/useQuery.test.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
act,
44
waitForElement,
55
fireEvent,
6-
cleanup,
76
} from '@testing-library/react'
87
import * as React from 'react'
98

@@ -13,7 +12,6 @@ import { sleep } from './utils'
1312
describe('useQuery', () => {
1413
afterEach(() => {
1514
queryCache.clear()
16-
cleanup()
1715
})
1816

1917
// See https://github.com/tannerlinsley/react-query/issues/105

0 commit comments

Comments
 (0)