62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
export interface InflightRequest {
|
|
id?: string;
|
|
model: string;
|
|
req_path?: string;
|
|
method?: string;
|
|
timestamp?: string;
|
|
elapsed_ms?: number;
|
|
}
|
|
|
|
export interface ModelState {
|
|
id: string;
|
|
state: string;
|
|
}
|
|
|
|
export type FeedEvent =
|
|
| { type: "inflight"; operation: "snapshot" | "add"; requests: InflightRequest[] }
|
|
| { type: "inflight"; operation: "remove"; id: string }
|
|
| { type: "activity"; id: number }
|
|
| { type: "modelStatus"; models: ModelState[] };
|
|
|
|
export type ModelRuntimeState = "stopped" | "loading" | "ready";
|
|
|
|
export class InflightTracker {
|
|
private requests = new Map<string, string>();
|
|
private states = new Map<string, ModelRuntimeState>();
|
|
|
|
apply(event: FeedEvent): void {
|
|
if (event.type === "inflight") {
|
|
if (event.operation === "snapshot") {
|
|
this.requests = new Map<string, string>();
|
|
for (const r of event.requests) if (r.id) this.requests.set(r.id, r.model);
|
|
} else if (event.operation === "add") {
|
|
for (const r of event.requests) if (r.id) this.requests.set(r.id, r.model);
|
|
} else if (event.operation === "remove") {
|
|
this.requests.delete(event.id);
|
|
}
|
|
} else if (event.type === "modelStatus") {
|
|
for (const m of event.models) this.states.set(m.id, normalizeState(m.state));
|
|
}
|
|
}
|
|
|
|
count(modelId: string): number {
|
|
let n = 0;
|
|
for (const model of this.requests.values()) if (model === modelId) n++;
|
|
return n;
|
|
}
|
|
|
|
total(): number {
|
|
return this.requests.size;
|
|
}
|
|
|
|
state(modelId: string): ModelRuntimeState | undefined {
|
|
return this.states.get(modelId);
|
|
}
|
|
}
|
|
|
|
function normalizeState(state: string): ModelRuntimeState {
|
|
if (state === "ready") return "ready";
|
|
if (state === "loading") return "loading";
|
|
return "stopped";
|
|
}
|