Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions src/__tests__/__snapshots__/server.caching.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,124 @@ exports[`memo should fire "onCacheRollout" callback on cache rollout, one entry
]
`;

exports[`memo should memoize a function, allow custom key hashing: async 1`] = `
[
{
"cacheKeys": [
"custom-hash-",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "[EMPTY]",
"type": "memo promise",
},
{
"cacheKeys": [
"custom-hash-",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "[EMPTY]",
"type": "memo promise",
},
{
"cacheKeys": [
"custom-hash-1",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "1",
"type": "memo promise",
},
{
"cacheKeys": [
"custom-hash-1",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "1",
"type": "memo promise",
},
{
"cacheKeys": [
"custom-hash-2,true",
],
"cacheLength": 2,
"errorValue": "2",
"successValue": undefined,
"type": "memo promise",
},
{
"cacheKeys": [
"custom-hash-2,true",
],
"cacheLength": 2,
"errorValue": "2",
"successValue": undefined,
"type": "memo promise",
},
]
`;

exports[`memo should memoize a function, allow custom key hashing: sync 1`] = `
[
{
"cacheKeys": [
"custom-hash-",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "[EMPTY]",
"type": "memo",
},
{
"cacheKeys": [
"custom-hash-",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "[EMPTY]",
"type": "memo",
},
{
"cacheKeys": [
"custom-hash-1",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "1",
"type": "memo",
},
{
"cacheKeys": [
"custom-hash-1",
],
"cacheLength": 2,
"errorValue": undefined,
"successValue": "1",
"type": "memo",
},
{
"cacheKeys": [
"custom-hash-2,true",
],
"cacheLength": 2,
"errorValue": "2",
"successValue": undefined,
"type": "memo error",
},
{
"cacheKeys": [
"custom-hash-2,true",
],
"cacheLength": 2,
"errorValue": "2",
"successValue": undefined,
"type": "memo error",
},
]
`;

exports[`memo should memoize a function, cacheLimit: async 1`] = `
[
{
Expand Down
7 changes: 7 additions & 0 deletions src/__tests__/server.caching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ describe('memo', () => {
description: 'disable memoization when cacheLimit is zero',
options: { cacheLimit: 0 },
params: [[], [], [1], [1], [2, true], [2, true]]
},
{
description: 'allow custom key hashing',
options: {
keyHash: (value: unknown) => `custom-hash-${value}`
},
params: [[], [], [1], [1], [2, true], [2, true]]
}
])('should memoize a function, $description', async ({ options, params }) => {
const log: any[] = [];
Expand Down
8 changes: 7 additions & 1 deletion src/server.caching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* @template TReturn Array of cache entries.
*/
type MemoCache<TReturn> = Array<TReturn | Promise<TReturn> | { (): never; isError: boolean } | any>;

Check warning on line 9 in src/server.caching.ts

View workflow job for this annotation

GitHub Actions / Integration-checks (20.x)

Unexpected any. Specify a different type

Check warning on line 9 in src/server.caching.ts

View workflow job for this annotation

GitHub Actions / Integration-checks (24.x)

Unexpected any. Specify a different type

Check warning on line 9 in src/server.caching.ts

View workflow job for this annotation

GitHub Actions / Integration-checks (22.x)

Unexpected any. Specify a different type

/**
* Memo cache handler response parameters.
Expand Down Expand Up @@ -56,6 +56,7 @@
* @property [cacheLimit] Number of entries to cache before overwriting previous entries (default: 1)
* @property {MemoDebugHandler<TReturn>} [debug] Debug callback function
* @property [expire] Expandable milliseconds until cache expires
* @property [keyHash] Function to generate a predictable hash key from the provided arguments. Defaults to internal `generateHash`.
* @property {OnMemoCacheHandler<TReturn>} [onCacheExpire] Callback when cache expires. Only fires when the `expire` option is set.
* @property {OnMemoCacheHandler<TReturn>} [onCacheRollout] Callback when cache entries are rolled off due to cache limit.
*/
Expand All @@ -64,6 +65,7 @@
cacheLimit?: number;
debug?: MemoDebugHandler<TReturn>;
expire?: number;
keyHash?: (args: unknown[]) => unknown;
onCacheExpire?: OnMemoCacheHandler<TReturn>;
onCacheRollout?: OnMemoCacheHandler<TReturn>;
}
Expand Down Expand Up @@ -93,6 +95,7 @@
cacheLimit = 1,
debug = () => {},
expire,
keyHash = generateHash,
onCacheExpire,
onCacheRollout
}: MemoOptions<TReturn> = {}
Expand All @@ -104,6 +107,9 @@
const isOnCacheRolloutPromise = isPromise(onCacheRollout);
const isOnCacheRollout = typeof onCacheRollout === 'function' || isOnCacheRolloutPromise;
const updatedExpire = Number.parseInt(String(expire), 10) || undefined;
const setKey = function (value: unknown[]): unknown {
return keyHash.call(null, value);
};

const ized = function () {
const cache: MemoCache<TReturn> = [];
Expand Down Expand Up @@ -159,7 +165,7 @@
return bypassValue;
}

const key = generateHash(args);
const key = setKey(args);

// Parse, memoize and return the original value
if (cache.indexOf(key) < 0) {
Expand Down
Loading