ソースを参照

Refactor fs memo cache

SukkaW 1 年間 前
コミット
84bdc48a72
1 ファイル変更48 行追加67 行削除
  1. 48 67
      Build/lib/fs-memo.ts

+ 48 - 67
Build/lib/fs-memo.ts

@@ -44,92 +44,73 @@ export type FsMemoCacheOptions<T> = CacheApplyOption<T, string> & {
   ttl?: undefined | never
   ttl?: undefined | never
 };
 };
 
 
-export function cache<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;
+function createCache(onlyUseCachedIfFail: boolean) {
+  return function cache<Args extends Devalue[], T>(
+    fn: (...args: Args) => Promise<T>,
+    opt: FsMemoCacheOptions<T>
+  ): (...args: Args) => Promise<T> {
+    const fixedKey = fn.toString();
 
 
     if (opt.temporaryBypass) {
     if (opt.temporaryBypass) {
-      return fn(...args);
+      return fn;
     }
     }
 
 
-    const cached = fsMemoCache.get(cacheKey);
-    if (cached == null) {
-      console.log(picocolors.yellow('[cache] miss'), picocolors.gray(cacheName || cacheKey));
+    return async function cachedCb(...args: Args) {
+      const { stringify: devalueStringify } = await import('devalue');
 
 
-      const serializer = 'serializer' in opt ? opt.serializer : identity as any;
+      // 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 value = await fn(...args);
+      const cacheName = picocolors.gray(fn.name || fixedKey || cacheKey);
 
 
-      fsMemoCache.set(cacheKey, serializer(value), TTL);
-      return value;
-    }
+      const cached = fsMemoCache.get(cacheKey);
 
 
-    console.log(picocolors.green('[cache] hit'), picocolors.gray(cacheName || cacheKey));
+      const serializer = 'serializer' in opt ? opt.serializer : identity as any;
+      const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
 
 
-    fsMemoCache.updateTtl(cacheKey, TTL);
+      if (onlyUseCachedIfFail) {
+        try {
+          const value = await fn(...args);
 
 
-    const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
-    return deserializer(cached);
-  };
-}
+          console.log(picocolors.gray('[cache] update'), cacheName);
+          fsMemoCache.set(cacheKey, serializer(value), TTL);
 
 
-export function cachedOnlyFail<Args extends Devalue[], T>(
-  fn: (...args: Args) => Promise<T>,
-  opt: FsMemoCacheOptions<T>
-): (...args: Args) => Promise<T> {
-  const fixedKey = fn.toString();
+          return value;
+        } catch (e) {
+          if (cached == null) {
+            console.log(picocolors.red('[fail] and no cache, throwing'), cacheName);
+            throw e;
+          }
 
 
-  return async function cachedCb(...args: Args) {
-    const { stringify: devalueStringify } = await import('devalue');
+          fsMemoCache.updateTtl(cacheKey, TTL);
 
 
-    // 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('|');
+          console.log(picocolors.yellow('[fail] try cache'), cacheName);
 
 
-    const cacheName = fn.name || fixedKey;
+          return deserializer(cached);
+        }
+      } else {
+        if (cached == null) {
+          console.log(picocolors.yellow('[cache] miss'), cacheName);
 
 
-    if (opt.temporaryBypass) {
-      return fn(...args);
-    }
+          const value = await fn(...args);
 
 
-    const cached = fsMemoCache.get(cacheKey);
+          fsMemoCache.set(cacheKey, serializer(value), TTL);
+          return value;
+        }
 
 
-    try {
-      const value = await fn(...args);
+        console.log(picocolors.green('[cache] hit'), cacheName);
 
 
-      const serializer = 'serializer' in opt ? opt.serializer : identity as any;
-      fsMemoCache.set(cacheKey, serializer(value), TTL);
+        fsMemoCache.updateTtl(cacheKey, TTL);
 
 
-      return value;
-    } catch (e) {
-      if (cached == null) {
-        console.log(picocolors.red('[fail] and no cache, throwing'), picocolors.gray(cacheName || cacheKey));
-        throw e;
+        return deserializer(cached);
       }
       }
-
-      fsMemoCache.updateTtl(cacheKey, TTL);
-
-      console.log(picocolors.yellow('[fail] try cache'), picocolors.gray(cacheName || cacheKey));
-      const deserializer = 'deserializer' in opt ? opt.deserializer : identity as any;
-
-      return deserializer(cached);
-    }
+    };
   };
   };
 }
 }
+
+export const cache = createCache(false);
+export const cachedOnlyFail = createCache(true);