fix(replay): stream sealed perception overlays

This commit is contained in:
DCCONSTRUCTIONS
2026-07-30 00:51:14 +03:00
parent 091ab2671e
commit 2ab9e45548
10 changed files with 380 additions and 44 deletions
+66 -1
View File
@@ -13,10 +13,11 @@ from typing import Any
import pytest
from fastapi import APIRouter, HTTPException, Request, Response
from fastapi.responses import FileResponse
from fastapi.routing import APIRoute
import k1link.sessions.media as recorded_media_module
from k1link.compute import RecordedPerceptionVideo
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
from k1link.sessions import (
@@ -1383,6 +1384,70 @@ def test_recorded_perception_endpoint_returns_one_complete_optional_overlay(
assert empty.status_code == 204
def test_recorded_perception_endpoint_streams_validated_file_artifact(
tmp_path: Path,
) -> 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"RRF2file-backed-perception"
overlay = tmp_path / "sealed-perception.rrd"
overlay.write_bytes(payload)
digest = hashlib.sha256(payload).hexdigest()
calls: list[tuple[str, str, str]] = []
class Provider:
def materialize(
self,
session_id: str,
*,
application_id: str,
recording_id: str,
) -> RecordedPerceptionOverlayArtifact:
calls.append((session_id, application_id, recording_id))
return RecordedPerceptionOverlayArtifact(
path=overlay,
byte_length=len(payload),
sha256=digest,
)
def render(
self,
_session_id: str,
*,
application_id: str,
recording_id: str,
) -> bytes:
raise AssertionError(f"heap rendering must not run: {application_id}/{recording_id}")
router = build_session_router(store, perception_overlay_provider=Provider())
perception_route = endpoint(
router,
"/api/v1/observation-sessions/{session_id}/perception.rrd",
"POST",
)
response = asyncio.run(
perception_route(
session_id=session.name,
request=RecordedPerceptionRequest(
application_id="nodedc_mission_core_recorded",
recording_id="recording-001",
),
)
)
assert isinstance(response, FileResponse)
assert Path(response.path) == overlay
assert response.media_type == "application/vnd.rerun.rrd"
assert response.headers["content-length"] == str(len(payload))
assert response.headers["etag"] == f'"sha256:{digest}"'
assert response.headers["content-disposition"] == 'inline; filename="perception.rrd"'
assert str(overlay) not in str(response.headers)
assert calls == [(session.name, "nodedc_mission_core_recorded", "recording-001")]
def test_recorded_point_color_endpoint_is_strict_and_forwards_confined_command(
tmp_path: Path,
) -> None: