IKHSAN
EN Read in EnglishID

homeio

Publik

Fork dari doctor-io/homeio

Branch
main
Commit terakhir
958d74616 Oktober 2026

memoize-async.ts

Buka raw
import "server-only";

export type MemoizedAsync<T> = (() => Promise<T>) & {
  /**
   * Forgets the cached value, after the thing it describes has been changed.
   * A call already in flight started before the change: its result is not kept.
   */
  invalidate(): void;
};

/**
 * Reuses the result of `load` for `ttlMs`, and lets concurrent callers share the
 * call in flight. An expensive probe (one that spawns commands, say) then runs
 * at most once per `ttlMs`, however many requests and streams ask for it.
 *
 * A call that throws is not cached: the next caller tries again.
 */
export function memoizeAsync<T>(load: () => Promise<T>, ttlMs: number): MemoizedAsync<T> {
  let cached: { value: T; expiresAt: number } | null = null;
  let inFlight: Promise<T> | null = null;
  let generation = 0;

  const memoized = () => {
    if (cached && cached.expiresAt > Date.now()) {
      return Promise.resolve(cached.value);
    }
    if (inFlight) return inFlight;

    const startedIn = generation;
    const call = load()
      .then((value) => {
        if (startedIn === generation) {
          cached = { value, expiresAt: Date.now() + ttlMs };
        }
        return value;
      })
      .finally(() => {
        if (inFlight === call) inFlight = null;
      });
    inFlight = call;
    return call;
  };

  memoized.invalidate = () => {
    generation += 1;
    cached = null;
    inFlight = null;
  };

  return memoized;
}
byte
1.439
baris
52
Jenis
ts
Commit terakhir
16 Oktober 2026