framework
Version:
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
47 lines • 2.42 kB
TypeScript
/**
* A read-through cache for the dashboard's slow reads (#1028).
*
* The dashboard polls. Every session view asks for its branch's PR, twice (the worktree bar and
* the handoff summary), on every navigation and again every ten seconds — and `gh pr view` costs
* about 600ms against a local git read's ten. So the same answer was being bought over and over,
* and the panel waited for it each time.
*
* Three behaviours, and each one is load-bearing:
* - **single flight** — concurrent asks for the same key share one call, so two panels and a
* poll tick do not become three subprocesses
* - **stale while revalidate** — once a value exists it is returned immediately, and refreshed
* in the background when it is older than `ttlMs`; nobody waits twice for the same answer
* - **a budget on the cold ask** — the first ask waits only `budgetMs` for the answer before
* reporting `pending`, so a slow lookup delays one panel's extra detail rather than the page
*
* `pending` is not "failed": it means the answer is on its way and the next read will have it.
* A caller that must not act on a half-answer (offering to open a PR that may already exist)
* uses it to hold off.
*/
/** What a cached read answers with: the value, and whether it is still being fetched. */
export interface Cached<T> {
value: T | undefined;
/** True when no value is known yet and a read is still running. */
pending: boolean;
}
/** Clock seam, so the tests do not sleep. */
export type Now = () => number;
export interface CacheOptions {
/** How old a value may be before a background refresh is started. */
ttlMs?: number;
/** How long a first, uncached ask waits before reporting `pending`. */
budgetMs?: number;
now?: Now;
}
/**
* Read `key` through the cache, calling `load` when it is missing or stale.
*
* A failed load is not cached: it leaves whatever was there (a panel keeps showing the last PR it
* knew about rather than dropping it because gh hiccuped) and the next read tries again.
*/
export declare function cachedRead<T>(key: string, load: () => Promise<T>, options?: CacheOptions): Promise<Cached<T>>;
/** Drop what is cached under `key`, so the next read is a fresh one. */
export declare function invalidate(key: string): void;
/** Test seam: forget everything. */
export declare function clearCache(): void;
//# sourceMappingURL=cache.d.ts.map