fix(lab): enforce canonical replay runtime
This commit is contained in:
@@ -17,6 +17,7 @@ from fastapi.responses import FileResponse
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
import k1link.sessions.media as recorded_media_module
|
||||
import k1link.web.session_api as session_api_module
|
||||
from k1link.compute import RecordedPerceptionOverlayArtifact, RecordedPerceptionVideo
|
||||
from k1link.device_plugins.xgrids_k1 import xgrids_k1_archive_source
|
||||
from k1link.device_plugins.xgrids_k1.mqtt.capture import FRAME_HEADER, RAW_MAGIC
|
||||
@@ -458,6 +459,80 @@ def test_completed_recording_get_does_not_hold_delete_for_launch_lease(
|
||||
manager.close()
|
||||
|
||||
|
||||
def test_canonical_lab_spatial_frame_uses_ready_immutable_recording(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
sessions = repository / "sessions"
|
||||
session = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
|
||||
store = SessionStore(repository, data_dir=tmp_path / "data")
|
||||
store.reconcile_archive(xgrids_k1_archive_source(sessions))
|
||||
payload = b"sealed-spatial-recording"
|
||||
|
||||
def export_recording(source: Path, destination: Path) -> dict[str, object]:
|
||||
destination.write_bytes(payload)
|
||||
return {
|
||||
"source_sha256": hashlib.sha256(source.read_bytes()).hexdigest(),
|
||||
"rrd_sha256": hashlib.sha256(payload).hexdigest(),
|
||||
"rrd_bytes": len(payload),
|
||||
"timeline": "session_time",
|
||||
"timeline_start_ns": 0,
|
||||
"timeline_end_ns": 1_000_000_000,
|
||||
}
|
||||
|
||||
materializer = SessionRecordingMaterializer(store.data_dir, exporter=export_recording)
|
||||
command = store.prepare_replay(session.name)
|
||||
recording = materializer.materialize(command)
|
||||
manager = SessionRecordingPreparationManager(materializer)
|
||||
resolved = manager.resolve_cached(command)
|
||||
assert resolved is not None and resolved.recording is not None
|
||||
generation = hashlib.sha256(payload).hexdigest()
|
||||
expected = {
|
||||
"schema_version": "missioncore.canonical-recorded-lab-spatial-frame/v1",
|
||||
"target_time_ns": 500_000_000,
|
||||
"source_time_ns": 499_000_000,
|
||||
"pose_time_ns": 499_000_000,
|
||||
"trajectory_time_ns": 490_000_000,
|
||||
"body_frame": {
|
||||
"origin_map_xyz_m": [0.0, 0.0, 0.0],
|
||||
"basis_map_from_body": [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
|
||||
},
|
||||
"source_point_count": 1,
|
||||
"source_points_body_xyz_m": [[1.0, 2.0, 3.0]],
|
||||
"local_slam_body_xyz_m": [[0.0, 0.0, 0.0]],
|
||||
}
|
||||
|
||||
def spatial_frame(path: Path, sha256: str, time_ns: int) -> dict[str, object]:
|
||||
assert path == recording.path
|
||||
assert sha256 == generation
|
||||
assert time_ns == 500_000_000
|
||||
return expected
|
||||
|
||||
monkeypatch.setattr(session_api_module, "canonical_lab_spatial_frame", spatial_frame)
|
||||
router = build_session_router(
|
||||
store,
|
||||
recording_materializer=materializer,
|
||||
recording_preparation_manager=manager,
|
||||
)
|
||||
spatial_route = endpoint(
|
||||
router,
|
||||
"/api/v1/observation-sessions/{session_id}/canonical-lab/spatial-frame",
|
||||
"GET",
|
||||
)
|
||||
try:
|
||||
response = asyncio.run(spatial_route(
|
||||
session_id=session.name,
|
||||
generation=generation,
|
||||
time_ns=500_000_000,
|
||||
))
|
||||
assert json.loads(response.body) == expected
|
||||
assert response.headers["etag"] == f'"{generation}:499000000"'
|
||||
assert response.headers["cache-control"].endswith("immutable")
|
||||
finally:
|
||||
manager.close()
|
||||
|
||||
|
||||
def test_session_router_returns_seekable_recording_and_serves_byte_ranges(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user