fix: refcount StatsCache keys, keep registrations across config change, and tidy GPU/usage render paths
This commit is contained in:
+2
-5
@@ -12,7 +12,6 @@ class Runtime {
|
||||
private feed?: EventFeed;
|
||||
private poller?: MetricsPoller;
|
||||
private statsCache?: StatsCache;
|
||||
private statsUnsub?: () => void;
|
||||
private listeners = new Set<() => void>();
|
||||
|
||||
ensureConnections(cfg: LlamaSwapConfig): void {
|
||||
@@ -22,9 +21,7 @@ class Runtime {
|
||||
this.poller?.stop();
|
||||
this.feed = undefined;
|
||||
this.poller = undefined;
|
||||
this.statsUnsub?.();
|
||||
this.statsCache = undefined;
|
||||
this.statsUnsub = undefined;
|
||||
this.statsCache?.setConfig(cfg);
|
||||
this.cfg = cfg;
|
||||
}
|
||||
if (!this.feed) {
|
||||
@@ -46,7 +43,7 @@ class Runtime {
|
||||
}
|
||||
if (!this.statsCache) {
|
||||
this.statsCache = new StatsCache(cfg);
|
||||
this.statsUnsub = this.statsCache.onChange(() => this.emit());
|
||||
this.statsCache.onChange(() => this.emit());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-14
@@ -7,7 +7,8 @@ const ACTIVITY_THROTTLE_MS = 2000;
|
||||
export type FetchFn = (cfg: LlamaSwapConfig, modelId: string) => Promise<UsageStats | null>;
|
||||
|
||||
export class StatsCache {
|
||||
private keys = new Set<string>();
|
||||
private refs = new Map<string, number>();
|
||||
private refreshing = false;
|
||||
private values = new Map<string, UsageStats | undefined>();
|
||||
private listeners = new Set<() => void>();
|
||||
private timer?: ReturnType<typeof setInterval>;
|
||||
@@ -27,8 +28,7 @@ export class StatsCache {
|
||||
}
|
||||
|
||||
register(key: string): void {
|
||||
if (this.keys.has(key)) return;
|
||||
this.keys.add(key);
|
||||
this.refs.set(key, (this.refs.get(key) ?? 0) + 1);
|
||||
if (!this.timer) {
|
||||
void this.refresh();
|
||||
this.timer = setInterval(() => void this.refresh(), this.pollMs);
|
||||
@@ -36,11 +36,18 @@ export class StatsCache {
|
||||
}
|
||||
|
||||
unregister(key: string): void {
|
||||
this.keys.delete(key);
|
||||
this.values.delete(key);
|
||||
if (this.keys.size === 0 && this.timer) {
|
||||
clearInterval(this.timer);
|
||||
const count = (this.refs.get(key) ?? 0) - 1;
|
||||
if (count <= 0) {
|
||||
this.refs.delete(key);
|
||||
this.values.delete(key);
|
||||
} else {
|
||||
this.refs.set(key, count);
|
||||
}
|
||||
if (this.refs.size === 0) {
|
||||
if (this.timer) clearInterval(this.timer);
|
||||
this.timer = undefined;
|
||||
if (this.throttleTimer) clearTimeout(this.throttleTimer);
|
||||
this.throttleTimer = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,15 +66,21 @@ export class StatsCache {
|
||||
}
|
||||
|
||||
async refresh(): Promise<void> {
|
||||
this.lastRefresh = Date.now();
|
||||
for (const key of this.keys) {
|
||||
try {
|
||||
const stats = await this.fetchFn(this.cfg, key);
|
||||
if (stats) this.values.set(key, stats);
|
||||
} catch {
|
||||
if (this.refreshing) return;
|
||||
this.refreshing = true;
|
||||
try {
|
||||
for (const key of this.refs.keys()) {
|
||||
try {
|
||||
const stats = await this.fetchFn(this.cfg, key);
|
||||
if (stats) this.values.set(key, stats);
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.refreshing = false;
|
||||
this.lastRefresh = Date.now();
|
||||
this.emit();
|
||||
}
|
||||
this.emit();
|
||||
}
|
||||
|
||||
onChange(listener: () => void): () => void {
|
||||
|
||||
Reference in New Issue
Block a user