fix(replay): stream sealed perception overlays
This commit is contained in:
@@ -22,7 +22,10 @@ from k1link.sessions import SessionIntegrityError
|
||||
|
||||
from .jobs import CameraComputeJob, validate_camera_compute_job
|
||||
from .perception_epoch import validate_recorded_perception_epoch_result
|
||||
from .results import RecordedPerceptionOverlayError
|
||||
from .results import (
|
||||
RecordedPerceptionOverlayArtifact,
|
||||
RecordedPerceptionOverlayError,
|
||||
)
|
||||
|
||||
FUSION_SCHEMA = "missioncore.recorded-calibrated-fusion/v1"
|
||||
FUSION_IDENTITY_SCHEMA = "missioncore.recorded-calibrated-fusion-identity/v1"
|
||||
@@ -188,18 +191,77 @@ class RecordedPerceptionOverlayMux:
|
||||
application_id: str,
|
||||
recording_id: str,
|
||||
) -> bytes | None:
|
||||
payload = self.primary.render(
|
||||
materialized = self.materialize(
|
||||
session_id,
|
||||
application_id=application_id,
|
||||
recording_id=recording_id,
|
||||
)
|
||||
if not isinstance(materialized, RecordedPerceptionOverlayArtifact):
|
||||
return materialized
|
||||
try:
|
||||
payload = materialized.path.read_bytes()
|
||||
except OSError as exc:
|
||||
raise RecordedPerceptionOverlayError(
|
||||
"recorded perception cache became unavailable"
|
||||
) from exc
|
||||
if (
|
||||
len(payload) != materialized.byte_length
|
||||
or hashlib.sha256(payload).hexdigest() != materialized.sha256
|
||||
):
|
||||
raise RecordedPerceptionOverlayError(
|
||||
"recorded perception cache changed after validation"
|
||||
)
|
||||
return payload
|
||||
|
||||
def materialize(
|
||||
self,
|
||||
session_id: str,
|
||||
*,
|
||||
application_id: str,
|
||||
recording_id: str,
|
||||
) -> RecordedPerceptionOverlayArtifact | bytes | None:
|
||||
primary_materializer = getattr(self.primary, "materialize", None)
|
||||
payload = (
|
||||
primary_materializer(
|
||||
session_id,
|
||||
application_id=application_id,
|
||||
recording_id=recording_id,
|
||||
)
|
||||
if callable(primary_materializer)
|
||||
else self.primary.render(
|
||||
session_id,
|
||||
application_id=application_id,
|
||||
recording_id=recording_id,
|
||||
)
|
||||
)
|
||||
if payload is not None and not isinstance(
|
||||
payload, (bytes, RecordedPerceptionOverlayArtifact)
|
||||
):
|
||||
raise RecordedPerceptionOverlayError(
|
||||
"recorded perception provider returned an invalid artifact"
|
||||
)
|
||||
if payload is not None or self.fallback is None:
|
||||
return payload
|
||||
return self.fallback.render(
|
||||
session_id,
|
||||
application_id=application_id,
|
||||
recording_id=recording_id,
|
||||
)
|
||||
fallback_materializer = getattr(self.fallback, "materialize", None)
|
||||
if callable(fallback_materializer):
|
||||
fallback_payload = fallback_materializer(
|
||||
session_id,
|
||||
application_id=application_id,
|
||||
recording_id=recording_id,
|
||||
)
|
||||
else:
|
||||
fallback_payload = self.fallback.render(
|
||||
session_id,
|
||||
application_id=application_id,
|
||||
recording_id=recording_id,
|
||||
)
|
||||
if fallback_payload is not None and not isinstance(
|
||||
fallback_payload, (bytes, RecordedPerceptionOverlayArtifact)
|
||||
):
|
||||
raise RecordedPerceptionOverlayError(
|
||||
"recorded perception fallback returned an invalid artifact"
|
||||
)
|
||||
return fallback_payload
|
||||
|
||||
def status(self, session_id: str, *, recording_id: str) -> dict[str, Any]:
|
||||
primary_status = getattr(self.primary, "status", None)
|
||||
|
||||
Reference in New Issue
Block a user