fix(k1): stabilize repeated acquisition and live viewer recovery

This commit is contained in:
DCCONSTRUCTIONS
2026-07-29 01:55:12 +03:00
parent 37b8930527
commit 2a97cf28c0
28 changed files with 2776 additions and 286 deletions
+40 -16
View File
@@ -1,6 +1,8 @@
from __future__ import annotations
import json
import logging
import socket
import struct
import threading
import time
@@ -20,6 +22,7 @@ from k1link.viewer.rerun_bridge import (
RerunSceneSettings,
_live_time_panel,
_point_colors,
_select_available_grpc_port,
)
@@ -62,6 +65,33 @@ class DisconnectFailureRecording(FakeRecording):
raise RuntimeError("synthetic disconnect failure")
def test_rerun_port_selection_skips_a_recording_still_held_by_a_viewer(
caplog: pytest.LogCaptureFixture,
) -> None:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as occupied:
occupied.bind(("0.0.0.0", 0))
occupied.listen()
preferred_port = int(occupied.getsockname()[1])
selected_port = _select_available_grpc_port(preferred_port, search_span=8)
recording = FakeRecording()
with caplog.at_level(
logging.INFO,
logger="k1link.device_plugins.xgrids_k1.viewer_receiver",
):
bridge = RerunBridge(
grpc_port=preferred_port,
recording_factory=lambda _: recording, # type: ignore[arg-type]
)
assert selected_port != preferred_port
assert preferred_port < selected_port < preferred_port + 8
assert caplog.records[-1].event_code == "rerun_grpc_port_rotated"
assert caplog.records[-1].preferred_port == preferred_port
assert caplog.records[-1].selected_port == selected_port
bridge.close()
def _message(
topic: str,
payload: bytes,
@@ -266,7 +296,7 @@ def test_palettes_are_deterministic_and_custom_color_is_exact() -> None:
assert custom_over_rgb.tolist() == [[16, 32, 48], [16, 32, 48]]
def test_runtime_reuses_one_bridge_across_sequential_sessions(tmp_path: Path) -> None:
def test_runtime_owns_fresh_bridge_for_each_sequential_session(tmp_path: Path) -> None:
capture = tmp_path / "mqtt.raw.k1mqtt"
point_topic = "RealtimePointcloud"
pose_topic = "RealtimePath"
@@ -300,10 +330,12 @@ def test_runtime_reuses_one_bridge_across_sequential_sessions(tmp_path: Path) ->
encoding="utf-8",
)
recording = FakeRecording()
recordings: list[FakeRecording] = []
created: list[RerunBridge] = []
def bridge_factory(**kwargs: object) -> RerunBridge:
recording = FakeRecording()
recordings.append(recording)
bridge = RerunBridge(
recording_factory=lambda _: recording, # type: ignore[arg-type]
**kwargs, # type: ignore[arg-type]
@@ -329,8 +361,8 @@ def test_runtime_reuses_one_bridge_across_sequential_sessions(tmp_path: Path) ->
assert snapshot["metrics"]["mqtt_to_publish_ms"] is None
runtime.stop(wait_seconds=5.0)
assert runtime.snapshot()["phase"] == "idle"
assert runtime.snapshot()["rerun_grpc_url"] == "rerun+http://127.0.0.1:9876/proxy"
assert recording.disconnected is False
assert runtime.snapshot()["rerun_grpc_url"] is None
assert recordings[0].disconnected is True
runtime.start_replay(capture, speed=0.0)
deadline = time.monotonic() + 5.0
@@ -340,13 +372,12 @@ def test_runtime_reuses_one_bridge_across_sequential_sessions(tmp_path: Path) ->
time.sleep(0.05)
runtime.stop(wait_seconds=5.0)
assert len(created) == 1
assert len(created) == 2
assert runtime.snapshot()["metrics"]["pcl_frames"] == 1
assert runtime.snapshot()["rerun_grpc_url"] == "rerun+http://127.0.0.1:9876/proxy"
assert recording.disconnected is False
assert runtime.snapshot()["rerun_grpc_url"] is None
assert all(recording.disconnected for recording in recordings)
runtime.close()
assert runtime.snapshot()["rerun_grpc_url"] is None
assert recording.disconnected is True
def test_runtime_reports_bridge_close_failure_instead_of_false_idle(tmp_path: Path) -> None:
@@ -385,18 +416,11 @@ def test_runtime_reports_bridge_close_failure_instead_of_false_idle(tmp_path: Pa
time.sleep(0.01)
snapshot = runtime.snapshot()
assert snapshot["phase"] == "idle"
assert snapshot["rerun_grpc_url"] == "rerun+http://127.0.0.1:9876/proxy"
assert recording.disconnected is False
with pytest.raises(RuntimeError, match="synthetic disconnect failure"):
runtime.close()
snapshot = runtime.snapshot()
assert snapshot["phase"] == "error"
assert "synthetic disconnect failure" in snapshot["message"]
assert snapshot["rerun_grpc_url"] is None
assert recording.disconnected is True
runtime.close()
def test_close_during_blocked_factory_closes_the_late_bridge(tmp_path: Path) -> None: