The following is a simple in memory cache implementation for the aws lambda environment. be aware that this class will use the memory available to your lambda instance and will be cleared off of any data when all instances of your lambda die off and the cold start cycle begins.
import { CacheItem, IDate } from "./types";
// global variables to hold data between different lambda invokations
global.memCachedItems = {};
global.memCachedItemAges = {};
export class InMemoryCache {
private readonly now: IDate;
constructor(now: IDate = () => new Date()) {
this.now = now;
}
put(key: string, item: any, ttlSecs = 0): void {
global.memCachedItems[key] = item;
this.setAgeInSeconds(key, ttlSecs);
}
get<T>(key: string, ttlSecs = 0): CacheItem<T> {
return new CacheItem(
global.memCachedItems[key],
this.isStale(key, ttlSecs)
);
}
remove(key: string): void {
delete global.memCachedItems[key];
}
clear(): void {
global.memCachedItems = {};
}
private setAgeInSeconds(key: string, ageInSeconds: number) {
const now = this.now();
now.setSeconds(now.getSeconds() + ageInSeconds);
global.memCachedItemAges[key] = now;
}
private isStale = (key: string, ageInSeconds: number): boolean => {
const now = this.now();
const storedAge = global.memCachedItemAges[key];
if (!storedAge) return true;
const age = now.getTime() - storedAge.getTime();
return age >= ageInSeconds;
};
}
Types:
export class CacheItem<T> {
value: T;
isEmpty: boolean;
isStale: boolean;
constructor(value: T, isStale: boolean) {
this.value = value;
this.isEmpty = !value;
this.isStale = isStale;
}
}
export type IDate = () => Date; // allows for easier unit tests