Files
EasyCLIProxyAPI/src/services/refreshScheduler.ts
T
lzt404 9cf3878b28 perf: reduce background overhead and improve UI responsiveness
- Move blocking usage queries and core lifecycle operations to background
  workers, limit concurrency, and prevent overlapping core operations
- Coalesce statistics refreshes and consolidate category aggregations,
  reducing unfiltered analysis queries from 11 to 4
- Cache bundled model prices, reuse management API connections, and reduce
  redundant checks in the usage collector
- Throttle download progress and guide positioning updates, and avoid
  redundant renders when core status is unchanged
- Bound and coalesce configuration watcher events, and reuse a single
  model catalog refresh worker
- Stop scheduling remaining health checks when the dialog closes and
  limit backend health-check concurrency
- Replace overlapping OAuth polling with sequential requests, retry
  backoff, timeouts, and stale callback protection
- Add regression tests and a statistics benchmark script, and move
  performance verification documentation to agent_docs
2026-09-06 01:28:58 +08:00

67 lines
1.8 KiB
TypeScript

export function createRefreshScheduler(minIntervalMs = 1_000) {
type Task = () => Promise<void>;
type Completion = { promise: Promise<void>; resolve: () => void; reject: (error: unknown) => void };
let running = false;
let completedAt = -Infinity;
let pending: Task | null = null;
let urgent = false;
let completion: Completion | null = null;
let timer: ReturnType<typeof setTimeout> | null = null;
const pump = () => {
if (running || !pending) return;
if (timer !== null) clearTimeout(timer);
timer = null;
const delay = urgent ? 0 : Math.max(0, minIntervalMs - (performance.now() - completedAt));
if (delay > 0) {
timer = setTimeout(pump, delay);
return;
}
const task = pending;
const currentCompletion = completion!;
pending = null;
completion = null;
urgent = false;
running = true;
void (async () => {
try {
await task();
currentCompletion.resolve();
} catch (error) {
currentCompletion.reject(error);
} finally {
running = false;
completedAt = performance.now();
pump();
}
})();
};
return {
schedule(task: Task, immediate = false): Promise<void> {
pending = task;
urgent ||= immediate;
if (!completion) {
let resolve!: () => void;
let reject!: (error: unknown) => void;
const promise = new Promise<void>((onResolved, onRejected) => {
resolve = onResolved;
reject = onRejected;
});
completion = { promise, resolve, reject };
}
const result = completion.promise;
pump();
return result;
},
cancelPending() {
if (timer !== null) clearTimeout(timer);
timer = null;
pending = null;
urgent = false;
completion?.resolve();
completion = null;
},
};
}