Skip to content

Commit b038f3a

Browse files
committed
fix: resolve batch with pending values as well
this solves an issue where cachified would never resolve when two batches were executed in parallel with partially overlapping keys fix #119
1 parent 0ecc84f commit b038f3a

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/cachified.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,41 @@ describe('cachified', () => {
14131413
expect(cache.get('test-2')).toBe(undefined);
14141414
});
14151415

1416+
it('de-duplicates batched cache calls', async () => {
1417+
const cache = new Map<string, CacheEntry>();
1418+
1419+
function getValues(indexes: number[], callId: number) {
1420+
const batch = createBatch((freshIndexes: number[]) =>
1421+
freshIndexes.map((i) => `value-${i}-call-${callId}`),
1422+
);
1423+
1424+
return Promise.all(
1425+
indexes.map((index) =>
1426+
cachified({
1427+
cache,
1428+
key: `test-${index}`,
1429+
ttl: Infinity,
1430+
getFreshValue: batch.add(index),
1431+
}),
1432+
),
1433+
);
1434+
}
1435+
1436+
const batch1 = getValues([1, 2, 3], 1);
1437+
const batch2 = getValues([1, 2, 5], 2);
1438+
1439+
expect(await batch1).toEqual([
1440+
'value-1-call-1',
1441+
'value-2-call-1',
1442+
'value-3-call-1',
1443+
]);
1444+
expect(await batch2).toEqual([
1445+
'value-1-call-1',
1446+
'value-2-call-1',
1447+
'value-5-call-2',
1448+
]);
1449+
});
1450+
14161451
it('does not invoke onValue when value comes from cache', async () => {
14171452
const cache = new Map<string, CacheEntry>();
14181453
const onValue = jest.fn();

src/cachified.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Cache,
55
CacheEntry,
66
createContext,
7+
HANDLE,
78
} from './common';
89
import { CACHE_EMPTY, getCachedValue } from './getCachedValue';
910
import { getFreshValue } from './getFreshValue';
@@ -53,6 +54,8 @@ export async function cachified<Value>(
5354
if (pendingValues.has(key)) {
5455
const { value: pendingRefreshValue, metadata } = pendingValues.get(key)!;
5556
if (!shouldRefresh(metadata)) {
57+
/* Notify batch that we handled this call using pending value */
58+
context.getFreshValue[HANDLE]?.();
5659
report({ name: 'getFreshValueHookPending' });
5760
const value = await pendingRefreshValue;
5861
report({ name: 'done', value });

0 commit comments

Comments
 (0)