-
-
Notifications
You must be signed in to change notification settings - Fork 721
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce large cache for swr (#7470)
Previously, clearing the SWR cache cleared all entries. Now you can configure the cache size. 1. This makes the search more fluid. Previously, if you went back and forth on pages, you were always sent to the loading state. 2. This also solves the issue where the command bar search cleared the cache for all other searches. 3. Additionally, it addresses the problem where the global search cleared the cache for project search.
- Loading branch information
Showing
4 changed files
with
83 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { clearCacheEntries } from './useClearSWRCache'; | ||
|
||
describe('manageCacheEntries', () => { | ||
it('should clear old cache entries and keep the current one when SWR_CACHE_SIZE is not provided', () => { | ||
const cacheMock = new Map(); | ||
cacheMock.set('prefix-1', {}); | ||
cacheMock.set('prefix-2', {}); | ||
cacheMock.set('prefix-3', {}); | ||
|
||
clearCacheEntries(cacheMock, 'prefix-3', 'prefix-'); | ||
|
||
expect(cacheMock.has('prefix-1')).toBe(false); | ||
expect(cacheMock.has('prefix-2')).toBe(false); | ||
expect(cacheMock.has('prefix-3')).toBe(true); | ||
}); | ||
|
||
it('should keep the SWR_CACHE_SIZE entries and delete the rest', () => { | ||
const cacheMock = new Map(); | ||
cacheMock.set('prefix-1', {}); | ||
cacheMock.set('prefix-2', {}); | ||
cacheMock.set('prefix-3', {}); | ||
cacheMock.set('prefix-4', {}); | ||
|
||
clearCacheEntries(cacheMock, 'prefix-4', 'prefix-', 2); | ||
|
||
expect(cacheMock.has('prefix-4')).toBe(true); | ||
expect([...cacheMock.keys()].length).toBe(2); | ||
}); | ||
|
||
it('should handle case when SWR_CACHE_SIZE is larger than number of entries', () => { | ||
const cacheMock = new Map(); | ||
cacheMock.set('prefix-1', {}); | ||
cacheMock.set('prefix-2', {}); | ||
|
||
clearCacheEntries(cacheMock, 'prefix-2', 'prefix-', 5); | ||
|
||
expect(cacheMock.has('prefix-1')).toBe(true); | ||
expect(cacheMock.has('prefix-2')).toBe(true); | ||
}); | ||
|
||
it('should not delete entries that do not match the prefix', () => { | ||
const cacheMock = new Map(); | ||
cacheMock.set('prefix-1', {}); | ||
cacheMock.set('other-2', {}); | ||
cacheMock.set('prefix-3', {}); | ||
|
||
clearCacheEntries(cacheMock, 'prefix-3', 'prefix-', 2); | ||
|
||
expect(cacheMock.has('prefix-1')).toBe(true); | ||
expect(cacheMock.has('other-2')).toBe(true); | ||
expect(cacheMock.has('prefix-3')).toBe(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,33 @@ | ||
import { useSWRConfig } from 'swr'; | ||
|
||
type Cache = ReturnType<typeof useSWRConfig>['cache']; | ||
|
||
export const clearCacheEntries = ( | ||
cache: Cache, | ||
currentKey: string, | ||
clearPrefix: string, | ||
SWR_CACHE_SIZE = 1, | ||
) => { | ||
const keys = [...cache.keys()]; | ||
|
||
const filteredKeys = keys.filter( | ||
(key) => key.startsWith(clearPrefix) && key !== currentKey, | ||
); | ||
const keysToDelete = filteredKeys.slice(SWR_CACHE_SIZE - 1); | ||
|
||
keysToDelete.forEach((key) => cache.delete(key)); | ||
}; | ||
|
||
/** | ||
With dynamic search and filter parameters we want to prevent cache from growing extensively. | ||
We only keep the latest cache key `currentKey` and remove all other entries identified | ||
by the `clearPrefix` | ||
*/ | ||
export const useClearSWRCache = (currentKey: string, clearPrefix: string) => { | ||
export const useClearSWRCache = ( | ||
currentKey: string, | ||
clearPrefix: string, | ||
SWR_CACHE_SIZE = 1, | ||
) => { | ||
const { cache } = useSWRConfig(); | ||
const keys = [...cache.keys()]; | ||
keys.filter((key) => key !== currentKey && key.startsWith(clearPrefix)).map( | ||
(key) => cache.delete(key), | ||
); | ||
clearCacheEntries(cache, currentKey, clearPrefix, SWR_CACHE_SIZE); | ||
}; |