Skip to content

Commit d926e09

Browse files
committed
Reproduce early cache eviction with unit test
1 parent 70372e7 commit d926e09

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

packages/query-db-collection/tests/query.test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3750,6 +3750,87 @@ describe(`QueryCollection`, () => {
37503750
// Wait for final GC to process
37513751
expect(collection.size).toBe(0)
37523752
})
3753+
3754+
it(`should not immediately remove query data from cache when live query is GCed (respects cacheTime)`, async () => {
3755+
// Create a QueryClient with a longer cacheTime to test that data should persist
3756+
const testQueryClient = new QueryClient({
3757+
defaultOptions: {
3758+
queries: {
3759+
staleTime: 0,
3760+
gcTime: 300,
3761+
retry: false,
3762+
},
3763+
},
3764+
})
3765+
3766+
const queryKey = [`premature-gc-test`]
3767+
const items: Array<TestItem> = [
3768+
{ id: `1`, name: `Item 1` },
3769+
{ id: `2`, name: `Item 2` },
3770+
]
3771+
3772+
const queryFn = vi.fn().mockResolvedValue(items)
3773+
3774+
// Use on-demand mode so the query is only created when the live query needs it
3775+
// This ensures the subscription is passed when the query is created
3776+
const config: QueryCollectionConfig<TestItem> = {
3777+
id: `premature-gc-test`,
3778+
queryClient: testQueryClient,
3779+
queryKey,
3780+
queryFn,
3781+
getKey,
3782+
syncMode: `on-demand`, // Use on-demand mode so query is created with subscription
3783+
}
3784+
3785+
const options = queryCollectionOptions(config)
3786+
const collection = createCollection(options)
3787+
3788+
// Create a live query that uses the collection
3789+
// This creates a subscription that will trigger the unsubscribed event when cleaned up
3790+
const liveQuery = createLiveQueryCollection({
3791+
query: (q) =>
3792+
q
3793+
.from({ item: collection })
3794+
.select(({ item }) => ({ id: item.id, name: item.name })),
3795+
})
3796+
3797+
// Preload the live query - this will create the query with the subscription
3798+
await liveQuery.preload()
3799+
3800+
// Wait for data to load
3801+
await vi.waitFor(() => {
3802+
expect(queryFn).toHaveBeenCalledTimes(1)
3803+
expect(collection.size).toBe(2)
3804+
})
3805+
3806+
// Verify query data is in the cache
3807+
const cachedData = testQueryClient.getQueryData(
3808+
queryKey
3809+
) as Array<TestItem>
3810+
expect(cachedData).toBeDefined()
3811+
expect(cachedData).toEqual(items)
3812+
3813+
// Cleanup the live query - this triggers the unsubscribed event
3814+
await liveQuery.cleanup()
3815+
3816+
// Wait 100ms, the gcTime is set to 300ms, so data should remain in the cache
3817+
await new Promise((resolve) => setTimeout(resolve, 100))
3818+
3819+
// Data should remain in cache until gcTime elapses
3820+
const cachedDataAfterCleanup = testQueryClient.getQueryData(queryKey)
3821+
expect(cachedDataAfterCleanup).toBeDefined()
3822+
expect(cachedDataAfterCleanup).toEqual(items)
3823+
3824+
// Wait an additional 250ms to be sure the gcTime elapsed
3825+
await new Promise((resolve) => setTimeout(resolve, 250))
3826+
3827+
// Data should be removed from cache after gcTime elapses
3828+
const cachedDataAfterCacheTime = testQueryClient.getQueryData(queryKey)
3829+
expect(cachedDataAfterCacheTime).toBeUndefined()
3830+
3831+
// Cleanup
3832+
testQueryClient.clear()
3833+
})
37533834
})
37543835

37553836
describe(`Static queryKey with on-demand mode`, () => {

0 commit comments

Comments
 (0)