feat(observatory): expose attempt-bound recorded progress
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { after, before, test } from "node:test";
|
||||
import { createServer } from "vite";
|
||||
|
||||
let server;
|
||||
let decode;
|
||||
let label;
|
||||
let fetchProgress;
|
||||
const job = {
|
||||
jobId: "observatory-run-" + "1".repeat(32),
|
||||
sourceSessionId: "source-a", setupId: "m49-tgs",
|
||||
definitionSha256: "a".repeat(64), claimGeneration: 2, state: "running",
|
||||
publication: { state: "not-required" },
|
||||
};
|
||||
function view() {
|
||||
return {
|
||||
schema_version: "missioncore.observatory-recorded-progress-view/v1",
|
||||
job_id: job.jobId, source_session_id: job.sourceSessionId, setup_id: job.setupId,
|
||||
definition_sha256: job.definitionSha256, claim_generation: 2, state: "running",
|
||||
received_at_utc: "2026-09-03T12:00:00Z", age_seconds: 0.5,
|
||||
progress: {
|
||||
schema_version: "missioncore.observatory-recorded-progress/v1",
|
||||
claim_generation: 2, sequence: 4, phase_index: 2,
|
||||
phase: "computing", unit: "frames", completed: 3, total: 10,
|
||||
elapsed_seconds: 8, phase_elapsed_seconds: 5,
|
||||
},
|
||||
};
|
||||
}
|
||||
before(async () => {
|
||||
server = await createServer({ configFile: false, logLevel: "silent", server: { middlewareMode: true } });
|
||||
const module = await server.ssrLoadModule("/src/core/observatory/recordedProgress.ts");
|
||||
decode = module.decodeRecordedProgress;
|
||||
label = module.recordedProgressLabel;
|
||||
fetchProgress = module.fetchRecordedProgress;
|
||||
});
|
||||
after(async () => { await server?.close(); });
|
||||
|
||||
test("actual frame count is separate from completion and publication", () => {
|
||||
const progress = decode(view(), job);
|
||||
assert.equal(label(job, progress), "Обрабатываем запись · 3 / 10 кадров");
|
||||
assert.equal(label({ ...job, publication: { state: "pending" } }, progress), "Сохраняем результат");
|
||||
assert.doesNotMatch(label(job, progress), /%|завершён|FPS|ETA/);
|
||||
});
|
||||
test("unknown total never becomes a synthetic percentage", () => {
|
||||
const value = view();
|
||||
value.progress.total = null;
|
||||
assert.equal(label(job, decode(value, job)), "Обрабатываем запись · 3 кадров");
|
||||
value.progress.completed = 0;
|
||||
assert.equal(label(job, decode(value, job)), "Обрабатываем запись");
|
||||
});
|
||||
test("old source definition or attempt cannot flash as current progress", () => {
|
||||
for (const delta of [
|
||||
{ job_id: "other" }, { source_session_id: "other" }, { setup_id: "other" },
|
||||
{ definition_sha256: "b".repeat(64) }, { claim_generation: 1 },
|
||||
]) assert.throws(() => decode({ ...view(), ...delta }, job));
|
||||
assert.equal(decode({ ...view(), state: "succeeded" }, job), null);
|
||||
assert.equal(label({ ...job, claimGeneration: 3 }, decode(view(), job)), "Ожидаем данные расчёта");
|
||||
});
|
||||
test("invalid counters, invented phase and extra fields fail closed", () => {
|
||||
for (const delta of [
|
||||
{ completed: true }, { completed: 11 }, { completed: -1 }, { total: 0 },
|
||||
{ completed: Number.MAX_SAFE_INTEGER + 1 }, { phase: "done" }, { path: "/private" },
|
||||
{ phase_elapsed_seconds: 9 }, { claim_generation: 3 },
|
||||
]) assert.throws(() => decode({ ...view(), progress: { ...view().progress, ...delta } }, job));
|
||||
});
|
||||
test("missing and stale telemetry show no fabricated advancement", () => {
|
||||
assert.equal(decode({ ...view(), progress: null, age_seconds: null, received_at_utc: null }, job), null);
|
||||
assert.equal(label(job, null), "Ожидаем данные расчёта");
|
||||
assert.equal(label(job, decode({ ...view(), age_seconds: 30 }, job)), "Ожидаем обновление прогресса");
|
||||
});
|
||||
test("progress is a read-only request bound to the active job", async () => {
|
||||
const calls = [];
|
||||
const progress = await fetchProgress(job, { fetcher: async (path, init) => {
|
||||
calls.push([path, init.method ?? "GET"]);
|
||||
return new Response(JSON.stringify(view()));
|
||||
} });
|
||||
assert.deepEqual(calls, [[`/api/v1/observatory/runs/${job.jobId}/progress`, "GET"]]);
|
||||
assert.equal(progress.completed, 3);
|
||||
});
|
||||
Reference in New Issue
Block a user