mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 01:00:34 +08:00
Refactor fs memo cache
This commit is contained in:
parent
8e96c36ea0
commit
84bdc48a72
@ -44,12 +44,17 @@ export type FsMemoCacheOptions<T> = CacheApplyOption<T, string> & {
|
|||||||
ttl?: undefined | never
|
ttl?: undefined | never
|
||||||
};
|
};
|
||||||
|
|
||||||
export function cache<Args extends Devalue[], T>(
|
function createCache(onlyUseCachedIfFail: boolean) {
|
||||||
|
return function cache<Args extends Devalue[], T>(
|
||||||
fn: (...args: Args) => Promise<T>,
|
fn: (...args: Args) => Promise<T>,
|
||||||
opt: FsMemoCacheOptions<T>
|
opt: FsMemoCacheOptions<T>
|
||||||
): (...args: Args) => Promise<T> {
|
): (...args: Args) => Promise<T> {
|
||||||
const fixedKey = fn.toString();
|
const fixedKey = fn.toString();
|
||||||
|
|
||||||
|
if (opt.temporaryBypass) {
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
|
||||||
return async function cachedCb(...args: Args) {
|
return async function cachedCb(...args: Args) {
|
||||||
const { stringify: devalueStringify } = await import('devalue');
|
const { stringify: devalueStringify } = await import('devalue');
|
||||||
|
|
||||||
@ -60,76 +65,52 @@ export function cache<Args extends Devalue[], T>(
|
|||||||
xxhash64(devalueStringify(args))
|
xxhash64(devalueStringify(args))
|
||||||
])).join('|');
|
])).join('|');
|
||||||
|
|
||||||
const cacheName = fn.name || fixedKey;
|
const cacheName = picocolors.gray(fn.name || fixedKey || cacheKey);
|
||||||
|
|
||||||
if (opt.temporaryBypass) {
|
|
||||||
return fn(...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cached = fsMemoCache.get(cacheKey);
|
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 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));
|
|
||||||
|
|
||||||
fsMemoCache.updateTtl(cacheKey, TTL);
|
|
||||||
|
|
||||||
const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
|
const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
|
||||||
return deserializer(cached);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function cachedOnlyFail<Args extends Devalue[], T>(
|
|
||||||
fn: (...args: Args) => Promise<T>,
|
|
||||||
opt: FsMemoCacheOptions<T>
|
|
||||||
): (...args: Args) => Promise<T> {
|
|
||||||
const fixedKey = fn.toString();
|
|
||||||
|
|
||||||
return async function cachedCb(...args: Args) {
|
|
||||||
const { stringify: devalueStringify } = await import('devalue');
|
|
||||||
|
|
||||||
// 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 = (await Promise.all([
|
|
||||||
xxhash64(fixedKey),
|
|
||||||
xxhash64(devalueStringify(args))
|
|
||||||
])).join('|');
|
|
||||||
|
|
||||||
const cacheName = fn.name || fixedKey;
|
|
||||||
|
|
||||||
if (opt.temporaryBypass) {
|
|
||||||
return fn(...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cached = fsMemoCache.get(cacheKey);
|
|
||||||
|
|
||||||
|
if (onlyUseCachedIfFail) {
|
||||||
try {
|
try {
|
||||||
const value = await fn(...args);
|
const value = await fn(...args);
|
||||||
|
|
||||||
const serializer = 'serializer' in opt ? opt.serializer : identity as any;
|
console.log(picocolors.gray('[cache] update'), cacheName);
|
||||||
fsMemoCache.set(cacheKey, serializer(value), TTL);
|
fsMemoCache.set(cacheKey, serializer(value), TTL);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (cached == null) {
|
if (cached == null) {
|
||||||
console.log(picocolors.red('[fail] and no cache, throwing'), picocolors.gray(cacheName || cacheKey));
|
console.log(picocolors.red('[fail] and no cache, throwing'), cacheName);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsMemoCache.updateTtl(cacheKey, TTL);
|
fsMemoCache.updateTtl(cacheKey, TTL);
|
||||||
|
|
||||||
console.log(picocolors.yellow('[fail] try cache'), picocolors.gray(cacheName || cacheKey));
|
console.log(picocolors.yellow('[fail] try cache'), cacheName);
|
||||||
const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
|
|
||||||
|
return deserializer(cached);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cached == null) {
|
||||||
|
console.log(picocolors.yellow('[cache] miss'), cacheName);
|
||||||
|
|
||||||
|
const value = await fn(...args);
|
||||||
|
|
||||||
|
fsMemoCache.set(cacheKey, serializer(value), TTL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(picocolors.green('[cache] hit'), cacheName);
|
||||||
|
|
||||||
|
fsMemoCache.updateTtl(cacheKey, TTL);
|
||||||
|
|
||||||
return deserializer(cached);
|
return deserializer(cached);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const cache = createCache(false);
|
||||||
|
export const cachedOnlyFail = createCache(true);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user