fix(lab): стабилизировать нативный RAV004 replay

This commit is contained in:
DCCONSTRUCTIONS
2026-08-30 13:28:33 +03:00
parent f5ee42751d
commit 07453142c2
8 changed files with 418 additions and 17 deletions
+2 -1
View File
@@ -93,6 +93,7 @@ class _RecordedBlueprintStream:
eye_contract = (follow_trajectory, plan_view)
update_eye_controls = self._eye_contract != eye_contract
blueprint = blueprint_factory(update_eye_controls)
make_active = self._sequence == 0
self._blueprint_recording.set_time(
"blueprint",
sequence=self._sequence,
@@ -102,7 +103,7 @@ class _RecordedBlueprintStream:
self._blueprint_recording.flush(timeout_sec=5.0)
bindings.send_blueprint(
self._blueprint_memory.storage,
True,
make_active,
False,
self._transport_recording.to_native(),
)
+47 -4
View File
@@ -12,10 +12,10 @@ import zipfile
from collections.abc import Callable
from functools import lru_cache
from pathlib import Path, PurePosixPath
from typing import Any, Final, Literal
from typing import Annotated, Any, Final, Literal
import numpy as np
from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, HTTPException, Query
from fastapi.concurrency import run_in_threadpool
from fastapi.responses import FileResponse, JSONResponse, Response
from PIL import Image
@@ -298,10 +298,11 @@ def _build_vegetation_lab_router(
},
)
@router.post("/{result_id}/canonical-overlay.rrd")
async def get_canonical_rerun_overlay(
async def canonical_rerun_overlay_response(
result_id: str,
request: CanonicalLabRerunRequest,
*,
expected_base_generation_sha256: str | None = None,
) -> FileResponse:
"""Project LAB-only evidence into the base recording's native clock."""
@@ -319,6 +320,11 @@ def _build_vegetation_lab_router(
if recording is None:
raise HTTPException(status_code=409, detail="Canonical spatial recording is not ready")
recording_path, generation_sha256 = recording
if (
expected_base_generation_sha256 is not None
and expected_base_generation_sha256 != generation_sha256
):
raise HTTPException(status_code=412, detail="Canonical recording generation changed")
try:
expected_recording_id = await run_in_threadpool(
canonical_recording_id,
@@ -353,6 +359,43 @@ def _build_vegetation_lab_router(
},
)
@router.post("/{result_id}/canonical-overlay.rrd")
async def get_canonical_rerun_overlay(
result_id: str,
request: CanonicalLabRerunRequest,
) -> FileResponse:
"""Resolve the sealed sidecar for bounded non-viewer consumers."""
return await canonical_rerun_overlay_response(result_id, request)
@router.get("/{result_id}/canonical-overlay.rrd")
async def stream_canonical_rerun_overlay(
result_id: str,
application_id: Annotated[
Literal["nodedc_mission_core_recorded"],
Query(),
],
recording_id: Annotated[
str,
Query(
min_length=1,
max_length=128,
pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
),
],
generation: Annotated[str, Query(pattern=r"^[a-f0-9]{64}$")],
) -> FileResponse:
"""Stream one immutable LAB sidecar through Rerun's native HTTP receiver."""
return await canonical_rerun_overlay_response(
result_id,
CanonicalLabRerunRequest(
application_id=application_id,
recording_id=recording_id,
),
expected_base_generation_sha256=generation,
)
@router.get("/{result_id}/timeline")
def get_canonical_route_timeline(result_id: str) -> dict[str, object]:
candidate = _resolve_candidate(root_provider, definition, result_id)