On a long-lived SSE connection a missed remove leaves a stale request id in the tracker forever; llama-swap only sends a fresh snapshot on connect, so counts drifted up and stayed stuck. The tracker now timestamps each request id (upserts refresh it) and prunes ids not updated within 120s, on every inflight event and on a 30s runtime interval. Removes also accept numeric ids defensively.
138 lines
4.4 KiB
TypeScript
138 lines
4.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { decodeEvent } from "../src/lib/event-feed";
|
|
import type { SseMessage } from "../src/lib/sse";
|
|
|
|
test("decodeEvent parses an inflight snapshot", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({
|
|
type: "inflight",
|
|
data: JSON.stringify({
|
|
operation: "snapshot",
|
|
requests: [{ id: "14", model: "Qwen3.8-27B-NVFP4", req_path: "/v1/chat/completions", elapsed_ms: 165510 }],
|
|
}),
|
|
}),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.ok(ev);
|
|
assert.equal(ev.type, "inflight");
|
|
if (ev.type === "inflight") {
|
|
assert.equal(ev.operation, "snapshot");
|
|
assert.equal(ev.requests.length, 1);
|
|
assert.equal(ev.requests[0].model, "Qwen3.8-27B-NVFP4");
|
|
assert.equal(ev.requests[0].elapsed_ms, 165510);
|
|
}
|
|
});
|
|
|
|
test("decodeEvent parses an inflight add with a singular request field", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({
|
|
type: "inflight",
|
|
data: JSON.stringify({ operation: "add", request: { id: "9", model: "A" } }),
|
|
}),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.ok(ev && ev.type === "inflight");
|
|
if (ev && ev.type === "inflight") {
|
|
assert.equal(ev.operation, "add");
|
|
assert.equal(ev.requests[0].model, "A");
|
|
}
|
|
});
|
|
|
|
test("decodeEvent parses an inflight upsert as an add", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({
|
|
type: "inflight",
|
|
data: JSON.stringify({ operation: "upsert", request: { id: "820", model: "DeepSeek-V4-Flash-0731", elapsed_ms: 103 } }),
|
|
}),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.ok(ev && ev.type === "inflight");
|
|
if (ev && ev.type === "inflight") {
|
|
assert.equal(ev.operation, "add");
|
|
assert.equal(ev.requests[0].id, "820");
|
|
assert.equal(ev.requests[0].elapsed_ms, 103);
|
|
}
|
|
});
|
|
|
|
test("decodeEvent parses an inflight remove with a bare id", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({ type: "inflight", data: JSON.stringify({ operation: "remove", id: "817" }) }),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.deepEqual(ev, { type: "inflight", operation: "remove", id: "817" });
|
|
});
|
|
|
|
test("decodeEvent accepts a numeric id on remove", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({ type: "inflight", data: JSON.stringify({ operation: "remove", id: 820 }) }),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.deepEqual(ev, { type: "inflight", operation: "remove", id: "820" });
|
|
});
|
|
|
|
test("decodeEvent parses modelStatus", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({
|
|
type: "modelStatus",
|
|
data: JSON.stringify([
|
|
{ id: "DeepSeek-V4-Flash-0731", state: "ready" },
|
|
{ id: "Qwen3.8-27B-NVFP4", state: "stopped" },
|
|
]),
|
|
}),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.ok(ev && ev.type === "modelStatus");
|
|
if (ev && ev.type === "modelStatus") {
|
|
assert.equal(ev.models.length, 2);
|
|
assert.equal(ev.models[0].state, "ready");
|
|
}
|
|
});
|
|
|
|
test("decodeEvent returns null for unrelated or malformed events", () => {
|
|
assert.equal(decodeEvent({ event: "message", data: JSON.stringify({ type: "logData", data: "{}" }) }), null);
|
|
assert.equal(decodeEvent({ event: "message", data: "not json" }), null);
|
|
});
|
|
|
|
test("decodeEvent returns null when modelStatus data is not an array", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({
|
|
type: "modelStatus",
|
|
data: JSON.stringify({ id: "DeepSeek-V4-Flash-0731", state: "ready" }),
|
|
}),
|
|
};
|
|
assert.equal(decodeEvent(msg), null);
|
|
});
|
|
|
|
test("decodeEvent handles inflight with a non-array requests field and no request field", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({
|
|
type: "inflight",
|
|
data: JSON.stringify({ operation: "snapshot", requests: "oops" }),
|
|
}),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.ok(ev && ev.type === "inflight");
|
|
if (ev && ev.type === "inflight") {
|
|
assert.equal(ev.operation, "snapshot");
|
|
assert.deepEqual(ev.requests, []);
|
|
}
|
|
});
|
|
|
|
test("decodeEvent parses an activity event with an id", () => {
|
|
const msg: SseMessage = {
|
|
event: "message",
|
|
data: JSON.stringify({ type: "activity", data: JSON.stringify({ id: 817 }) }),
|
|
};
|
|
const ev = decodeEvent(msg);
|
|
assert.deepEqual(ev, { type: "activity", id: 817 });
|
|
});
|