| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- import path from 'node:path';
- import { Cache } from './cache-filesystem';
- import type { CacheApplyOption } from './cache-filesystem';
- import { isCI } from 'ci-info';
- import { Typeson, set, map, typedArrays } from 'typeson-registry';
- import picocolors from 'picocolors';
- import { identity } from './misc';
- const typeson = new Typeson().register([
- typedArrays,
- set,
- map
- ]);
- const fsMemoCache = new Cache({ cachePath: path.resolve(__dirname, '../../.cache'), tableName: 'fs_memo_cache' });
- const TTL = isCI
- // We run CI daily, so 1.5 days TTL is enough to persist the cache across runs
- ? 1.5 * 86400 * 1000
- // We run locally less frequently, so we need to persist the cache for longer, 7 days
- : 7 * 86400 * 1000;
- type TypesonValue =
- | string
- | number
- | boolean
- | null
- | Set<any>
- | Map<any, any>
- | TypesonObject
- | TypesonArray;
- interface TypesonObject {
- [key: string]: TypesonValue
- }
- interface TypesonArray extends Array<TypesonValue> { }
- export type FsMemoCacheOptions<T> = CacheApplyOption<T, string> & {
- ttl?: undefined | never
- };
- export function cache<Args extends TypesonValue[], T>(
- fn: (...args: Args) => Promise<T>,
- opt: FsMemoCacheOptions<T>
- ): (...args: Args) => Promise<T> {
- // TODO if cb.toString() is long we should hash it
- const fixedKey = fn.toString();
- return async function cachedCb(...args: Args) {
- // Construct the complete cache key for this function invocation
- // typeson.stringify is still limited. For now we uses typescript to guard the args.
- const cacheKey = `${fixedKey}|${typeson.stringifySync(args)}`;
- const cacheName = fn.name || cacheKey;
- const { temporaryBypass, incrementTtlWhenHit } = opt;
- if (temporaryBypass) {
- return fn(...args);
- }
- const cached = fsMemoCache.get(cacheKey);
- if (cached == null) {
- console.log(picocolors.yellow('[cache] miss'), picocolors.gray(cacheName || cacheKey));
- const serializer = 'serializer' in opt ? opt.serializer : identity as any;
- const value = await fn(...args);
- fsMemoCache.set(cacheKey, serializer(value), TTL);
- return value;
- }
- console.log(picocolors.green('[cache] hit'), picocolors.gray(cacheName || cacheKey));
- if (incrementTtlWhenHit) {
- fsMemoCache.updateTtl(cacheKey, TTL);
- }
- const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
- return deserializer(cached);
- };
- }
|