Skip to content

Commit

Permalink
feat(keys): enable accurate retrieval of all valid cache keys
Browse files Browse the repository at this point in the history
  • Loading branch information
uladkasach committed Nov 24, 2022
1 parent 32a4663 commit 5a70816
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
28 changes: 28 additions & 0 deletions src/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,32 @@ describe('cache', () => {
const iceCreamStateAfter5Sec = get('ice cream state');
expect(iceCreamStateAfter5Sec).toEqual(undefined); // no longer defined, since the item level seconds until expiration was 5
});
it('should accurately get keys', () => {
// create the cache
const { set, keys } = createCache();

// check key is added when value is set
set('meaning-of-life', '42');
const keys1 = keys();
expect(keys1.length).toEqual(1);
expect(keys1[0]).toEqual('meaning-of-life');

// check that there are no duplicates when key value is updated
set('meaning-of-life', '42.0');
const keys2 = keys();
expect(keys2.length).toEqual(1);
expect(keys2[0]).toEqual('meaning-of-life');

// check that multiple keys can be set
set('purpose-of-life', 'propagation');
const keys3 = keys();
expect(keys3.length).toEqual(2);
expect(keys3[1]).toEqual('purpose-of-life');

// check that invalidation removes the key
set('meaning-of-life', undefined);
const keys4 = keys();
expect(keys4.length).toEqual(1);
expect(keys4[0]).toEqual('purpose-of-life');
});
});
22 changes: 20 additions & 2 deletions src/cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface SimpleInMemoryCache<T> {
get: (key: string) => T | undefined;
set: (key: string, value: T, options?: { secondsUntilExpiration?: number }) => void;
keys: () => string[];
}

export interface SimpleInMemoryCacheState<T> {
Expand All @@ -16,7 +17,18 @@ export const createCache = <T>({ defaultSecondsUntilExpiration = 5 * 60 }: { def
const cache: SimpleInMemoryCacheState<T> = {};

// define how to set an item into the cache
const set = (key: string, value: T, { secondsUntilExpiration = defaultSecondsUntilExpiration }: { secondsUntilExpiration?: number } = {}) => {
const set = (
key: string,
value: T | undefined,
{ secondsUntilExpiration = defaultSecondsUntilExpiration }: { secondsUntilExpiration?: number } = {},
) => {
// handle cache invalidation
if (value === undefined) {
delete cache[key];
return;
}

// handle setting
const expiresAtMse = getMseNow() + secondsUntilExpiration * 1000;
cache[key] = { value, expiresAtMse };
};
Expand All @@ -29,6 +41,12 @@ export const createCache = <T>({ defaultSecondsUntilExpiration = 5 * 60 }: { def
return cacheContent.value; // otherwise, its in the cache and not expired, so return the value
};

// define how to grab all valid keys
const keys = () =>
Object.entries(cache)
.filter(([_, value]) => value.expiresAtMse > getMseNow())
.map(([key]) => key);

// return the api
return { set, get };
return { set, get, keys };
};

0 comments on commit 5a70816

Please sign in to comment.