feat(simulation): add Polygon live worker gateway
This commit is contained in:
@@ -10,6 +10,13 @@ let fetchPolygonRunCatalog;
|
||||
let fetchPolygonRunDetail;
|
||||
let resolvePolygonRunRoute;
|
||||
let PolygonRunContractError;
|
||||
let decodePolygonWorkerStatus;
|
||||
let decodePolygonVehicleState;
|
||||
let fetchPolygonWorkerStatus;
|
||||
let fetchPolygonVehicleState;
|
||||
let startPolygonWorker;
|
||||
let stopPolygonWorker;
|
||||
let PolygonWorkerContractError;
|
||||
let workspaceById;
|
||||
let workspacesForRoot;
|
||||
|
||||
@@ -27,6 +34,15 @@ before(async () => {
|
||||
resolvePolygonRunRoute,
|
||||
PolygonRunContractError,
|
||||
} = await server.ssrLoadModule("/src/core/polygon/runArchive.ts"));
|
||||
({
|
||||
decodePolygonWorkerStatus,
|
||||
decodePolygonVehicleState,
|
||||
fetchPolygonWorkerStatus,
|
||||
fetchPolygonVehicleState,
|
||||
startPolygonWorker,
|
||||
stopPolygonWorker,
|
||||
PolygonWorkerContractError,
|
||||
} = await server.ssrLoadModule("/src/core/polygon/liveWorker.ts"));
|
||||
({ workspaceById, workspacesForRoot } = await server.ssrLoadModule("/src/productModel.ts"));
|
||||
});
|
||||
|
||||
@@ -148,6 +164,60 @@ function jsonResponse(payload, status = 200) {
|
||||
});
|
||||
}
|
||||
|
||||
function workerStatus(overrides = {}) {
|
||||
return {
|
||||
schema_version: "missioncore.simulation-worker-status/v1",
|
||||
worker_id: "mission-gpu-s1",
|
||||
transport: "unix",
|
||||
mode: "simulation",
|
||||
available: true,
|
||||
control_available: true,
|
||||
active_run_id: "s1c-6cb1495-20260724t180000z-aabbcc",
|
||||
run_state: "running",
|
||||
provider_ids: ["micro-xrce-dds-agent", "px4-gazebo-stock-rover"],
|
||||
isolation: {
|
||||
network: "loopback-only-netns",
|
||||
process_identity: "missioncore",
|
||||
artifact_policy: "d-only",
|
||||
},
|
||||
authority: {
|
||||
scope: "virtual-only",
|
||||
actuator_authority: false,
|
||||
direct_actuator_setpoints_allowed: false,
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function vehicleState(overrides = {}) {
|
||||
return {
|
||||
schema_version: "missioncore.vehicle-state/v1",
|
||||
run_id: "s1c-6cb1495-20260724t180000z-aabbcc",
|
||||
sequence: 7,
|
||||
observed_at_utc: "2026-07-24T18:00:07Z",
|
||||
host_monotonic_ns: 123_456_789,
|
||||
sim_time_ns: 7_000_000_000,
|
||||
frame_id: "map_enu",
|
||||
child_frame_id: "base_link_flu",
|
||||
pose: {
|
||||
position_m: { x: 1.25, y: -0.5, z: 0.18 },
|
||||
orientation_xyzw: { x: 0, y: 0, z: 0.1, w: 0.995 },
|
||||
},
|
||||
source: {
|
||||
provider: "gazebo",
|
||||
topic: "/world/rover/dynamic_pose/info",
|
||||
signal: "ground-truth",
|
||||
quality: "diagnostic",
|
||||
},
|
||||
safety: {
|
||||
scope: "virtual-only",
|
||||
actuator_authority: false,
|
||||
navigation_or_safety_accepted: false,
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test("UI-0 route is direct-only and does not add Polygon to system navigation", () => {
|
||||
assert.deepEqual(resolvePolygonRunRoute("?workspace=polygon-run"), {
|
||||
active: true,
|
||||
@@ -228,3 +298,64 @@ test("Polygon fetchers use bounded same-origin GET endpoints", async () => {
|
||||
assert.ok(calls.every(({ init }) => init.method === "GET"));
|
||||
assert.ok(calls.every(({ init }) => init.headers.Accept === "application/json"));
|
||||
});
|
||||
|
||||
test("Polygon Live decodes only D-only virtual diagnostic state", () => {
|
||||
const status = decodePolygonWorkerStatus(workerStatus());
|
||||
const live = decodePolygonVehicleState(vehicleState());
|
||||
|
||||
assert.equal(status.available, true);
|
||||
assert.equal(status.activeRunId, live.runId);
|
||||
assert.equal(status.isolation.artifactPolicy, "d-only");
|
||||
assert.deepEqual(live.position, { x: 1.25, y: -0.5, z: 0.18 });
|
||||
assert.throws(
|
||||
() => decodePolygonWorkerStatus(workerStatus({
|
||||
authority: {
|
||||
...workerStatus().authority,
|
||||
actuator_authority: true,
|
||||
},
|
||||
})),
|
||||
PolygonWorkerContractError,
|
||||
);
|
||||
assert.throws(
|
||||
() => decodePolygonVehicleState(vehicleState({
|
||||
source: {
|
||||
...vehicleState().source,
|
||||
quality: "accepted",
|
||||
},
|
||||
})),
|
||||
PolygonWorkerContractError,
|
||||
);
|
||||
});
|
||||
|
||||
test("Polygon Live uses same-origin gateway and idempotent lifecycle requests", async () => {
|
||||
const calls = [];
|
||||
const stopped = workerStatus({
|
||||
active_run_id: null,
|
||||
run_state: null,
|
||||
provider_ids: [],
|
||||
});
|
||||
const fetcher = async (url, init) => {
|
||||
calls.push({ url: String(url), init });
|
||||
if (String(url).endsWith("/live")) return jsonResponse(vehicleState());
|
||||
if (String(url).endsWith("/stop")) return jsonResponse(stopped);
|
||||
return jsonResponse(workerStatus());
|
||||
};
|
||||
|
||||
await fetchPolygonWorkerStatus({ fetcher });
|
||||
await fetchPolygonVehicleState({ fetcher });
|
||||
await startPolygonWorker({ idempotencyKey: "start-001", fetcher });
|
||||
await stopPolygonWorker("s1c-6cb1495-20260724t180000z-aabbcc", {
|
||||
idempotencyKey: "stop-001",
|
||||
fetcher,
|
||||
});
|
||||
|
||||
assert.deepEqual(calls.map(({ url }) => url), [
|
||||
"/api/v1/polygon/worker",
|
||||
"/api/v1/polygon/worker/live",
|
||||
"/api/v1/polygon/worker/runs",
|
||||
"/api/v1/polygon/worker/runs/s1c-6cb1495-20260724t180000z-aabbcc/stop",
|
||||
]);
|
||||
assert.equal(calls[2].init.headers["Idempotency-Key"], "start-001");
|
||||
assert.equal(calls[3].init.headers["Idempotency-Key"], "stop-001");
|
||||
assert.equal(calls[2].init.body, JSON.stringify({ scenario_id: "stock-rover-ackermann" }));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user