diff --git a/src/cachified.spec.ts b/src/cachified.spec.ts index c55d556..52053e1 100644 --- a/src/cachified.spec.ts +++ b/src/cachified.spec.ts @@ -1413,6 +1413,41 @@ describe('cachified', () => { expect(cache.get('test-2')).toBe(undefined); }); + it('de-duplicates batched cache calls', async () => { + const cache = new Map(); + + function getValues(indexes: number[], callId: number) { + const batch = createBatch((freshIndexes: number[]) => + freshIndexes.map((i) => `value-${i}-call-${callId}`), + ); + + return Promise.all( + indexes.map((index) => + cachified({ + cache, + key: `test-${index}`, + ttl: Infinity, + getFreshValue: batch.add(index), + }), + ), + ); + } + + const batch1 = getValues([1, 2, 3], 1); + const batch2 = getValues([1, 2, 5], 2); + + expect(await batch1).toEqual([ + 'value-1-call-1', + 'value-2-call-1', + 'value-3-call-1', + ]); + expect(await batch2).toEqual([ + 'value-1-call-1', + 'value-2-call-1', + 'value-5-call-2', + ]); + }); + it('does not invoke onValue when value comes from cache', async () => { const cache = new Map(); const onValue = jest.fn(); diff --git a/src/cachified.ts b/src/cachified.ts index e23a974..71b6f54 100644 --- a/src/cachified.ts +++ b/src/cachified.ts @@ -4,6 +4,7 @@ import { Cache, CacheEntry, createContext, + HANDLE, } from './common'; import { CACHE_EMPTY, getCachedValue } from './getCachedValue'; import { getFreshValue } from './getFreshValue'; @@ -53,6 +54,8 @@ export async function cachified( if (pendingValues.has(key)) { const { value: pendingRefreshValue, metadata } = pendingValues.get(key)!; if (!shouldRefresh(metadata)) { + /* Notify batch that we handled this call using pending value */ + context.getFreshValue[HANDLE]?.(); report({ name: 'getFreshValueHookPending' }); const value = await pendingRefreshValue; report({ name: 'done', value });