Skip to content

Commit

Permalink
fix: resolve batch with pending values as well
Browse files Browse the repository at this point in the history
this solves an issue where cachified would never resolve when
two batches were executed in parallel with partially overlapping keys

fix #119
  • Loading branch information
Xiphe committed Feb 7, 2025
1 parent 0ecc84f commit b038f3a
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/cachified.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,41 @@ describe('cachified', () => {
expect(cache.get('test-2')).toBe(undefined);
});

it('de-duplicates batched cache calls', async () => {
const cache = new Map<string, CacheEntry>();

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<string, CacheEntry>();
const onValue = jest.fn();
Expand Down
3 changes: 3 additions & 0 deletions src/cachified.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Cache,
CacheEntry,
createContext,
HANDLE,
} from './common';
import { CACHE_EMPTY, getCachedValue } from './getCachedValue';
import { getFreshValue } from './getFreshValue';
Expand Down Expand Up @@ -53,6 +54,8 @@ export async function cachified<Value>(
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 });
Expand Down

0 comments on commit b038f3a

Please sign in to comment.