baublet/w8mngr

View on GitHub
api/helpers/globalInMemoryCache.ts

Summary

Maintainability
A
0 mins
Test Coverage
import hash from "object-hash";
import { log } from "../config/log";

const cache = new Map<string, { value: any; expiry: number }>();

export const globalInMemoryCache = {
  clear: (key: string) => cache.delete(key),
  getOrSet: async <T>({
    key,
    expiry = Date.now() + 1000 * 30, // 30 seconds by default
    fn,
  }: {
    key: any;
    /**
     * Key expiry date in milliseconds
     */
    expiry?: number;
    fn: () => Promise<T>;
  }): Promise<T> => {
    const keyHash = hash({ key });

    const existingRecord = cache.get(keyHash);
    const now = Date.now();
    if (existingRecord && existingRecord.expiry + now > now) {
      log("debug", `Cache hit for key ${JSON.stringify(key)}`);
      return existingRecord.value;
    }

    try {
      const newValue = await fn();
      cache.set(keyHash, {
        value: newValue,
        expiry,
      });
      log(
        "debug",
        `Cache miss for key ${JSON.stringify(
          key
        )}. Saving to cache for ${expiry}ms`
      );

      return newValue;
    } catch (error) {
      log("error", "getOrSet cache function error", {
        error,
      });
      throw error;
    }
  },
};