mirror of
https://github.com/hansjone/netx.git
synced 2026-10-15 09:50:55 +08:00
Add collect stop, cutover nav prefetch/cache, and lane labels.
Let operators abort queued/running biz_state batches, speed cutover page switches, and show light/heavy collect lanes on monitor items. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
305822aa4f
commit
924f9bd2f7
16 changed files with 779 additions and 112 deletions
60
web/src/pages/network/cutoverDataCache.ts
Normal file
60
web/src/pages/network/cutoverDataCache.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Short-lived cache for cutover list APIs.
|
||||
* Switching biz-state / compare / migration / templates remounts each page;
|
||||
* without cache every click re-waits on Promise.all network round-trips.
|
||||
*/
|
||||
|
||||
type Entry = { at: number; data: unknown };
|
||||
|
||||
const store = new Map<string, Entry>();
|
||||
const DEFAULT_TTL_MS = 45_000;
|
||||
|
||||
export async function cutoverCachedGet<T>(
|
||||
key: string,
|
||||
fetcher: () => Promise<T>,
|
||||
opts?: { force?: boolean; ttlMs?: number },
|
||||
): Promise<T> {
|
||||
const ttl = opts?.ttlMs ?? DEFAULT_TTL_MS;
|
||||
if (!opts?.force) {
|
||||
const hit = store.get(key);
|
||||
if (hit && Date.now() - hit.at < ttl) {
|
||||
return hit.data as T;
|
||||
}
|
||||
}
|
||||
const data = await fetcher();
|
||||
store.set(key, { at: Date.now(), data });
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Return stale immediately (if any), refresh in background and notify. */
|
||||
export async function cutoverCachedGetSWR<T>(
|
||||
key: string,
|
||||
fetcher: () => Promise<T>,
|
||||
onFresh?: (data: T) => void,
|
||||
): Promise<T> {
|
||||
const hit = store.get(key);
|
||||
if (hit) {
|
||||
void fetcher()
|
||||
.then((data) => {
|
||||
store.set(key, { at: Date.now(), data });
|
||||
onFresh?.(data);
|
||||
})
|
||||
.catch(() => {
|
||||
/* keep stale */
|
||||
});
|
||||
return hit.data as T;
|
||||
}
|
||||
const data = await fetcher();
|
||||
store.set(key, { at: Date.now(), data });
|
||||
return data;
|
||||
}
|
||||
|
||||
export function invalidateCutoverCache(prefix = ""): void {
|
||||
if (!prefix) {
|
||||
store.clear();
|
||||
return;
|
||||
}
|
||||
for (const k of [...store.keys()]) {
|
||||
if (k.startsWith(prefix)) store.delete(k);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue