wip(k1): checkpoint connection recovery rewrite
Capture the current unreleased K1 connection, recovery, lifecycle, viewer, and test work as a single known-bad baseline for subsequent fixes.
This commit is contained in:
@@ -3,15 +3,28 @@ import type {
|
||||
ObservationSourceAvailability,
|
||||
ObservationSourceDelivery,
|
||||
ObservationSourceDescriptor,
|
||||
ObservationSourcePresentationLease,
|
||||
ObservationSourceProvider,
|
||||
} from "@mission-core/plugin-sdk";
|
||||
import { confirmedRuntimeSourceMode, effectiveAcquisition } from "./lifecycle";
|
||||
import {
|
||||
activeStreamRecoveredBrowserAuthority,
|
||||
activeStreamRecoveryOwnsPresentationDecision,
|
||||
activeStreamRecoveryPresentationAuthority,
|
||||
type ActiveStreamRecoveryPresentationAuthority,
|
||||
} from "./activeStreamRecovery";
|
||||
import {
|
||||
confirmedRuntimeSourceMode,
|
||||
effectiveAcquisition,
|
||||
hasAuthoritativeData,
|
||||
hasControlAuthority,
|
||||
} from "./lifecycle";
|
||||
import { xgridsK1Manifest } from "./manifest";
|
||||
import type {
|
||||
XgridsCameraPreviewDelivery,
|
||||
XgridsK1State,
|
||||
XgridsSensorCatalogStream,
|
||||
} from "./api";
|
||||
import { isXgridsActiveStreamRecovery } from "./api";
|
||||
|
||||
function providerFor(
|
||||
state: XgridsK1State,
|
||||
@@ -22,30 +35,72 @@ function providerFor(
|
||||
pluginVersion: xgridsK1Manifest.metadata.version,
|
||||
modelId: state.device_ref?.model_id || activeModel.id,
|
||||
compatibilityProfileId:
|
||||
state.device_session?.compatibility_profile_id ?? state.compatibility?.profile_id ?? null,
|
||||
(state.connection_supervisor?.observed.device_identity.state === "verified"
|
||||
? state.connection_supervisor.observed.device_identity.compatibility_profile_id
|
||||
: null)
|
||||
?? state.device_session?.compatibility_profile_id
|
||||
?? state.compatibility?.profile_id
|
||||
?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function bindingFor(state: XgridsK1State) {
|
||||
function bindingFor(
|
||||
state: XgridsK1State,
|
||||
recoveryAuthority: ActiveStreamRecoveryPresentationAuthority | null,
|
||||
) {
|
||||
const acquisition = effectiveAcquisition(state);
|
||||
const controlAuthoritative = hasControlAuthority(state);
|
||||
const recoveryAuthoritative = recoveryAuthority !== null;
|
||||
return {
|
||||
deviceId: state.device_ref?.device_id ?? null,
|
||||
deviceSessionId: state.device_session?.device_session_id ?? null,
|
||||
// A legacy snapshot may retain a selected device and session long after
|
||||
// the control topology has disappeared. Do not publish those values as a
|
||||
// live host binding until the supervisor has re-attested the topology.
|
||||
deviceId: recoveryAuthoritative
|
||||
? acquisition?.device_id?.trim() || null
|
||||
: controlAuthoritative ? state.device_ref?.device_id ?? null : null,
|
||||
deviceSessionId: recoveryAuthoritative
|
||||
? acquisition?.device_session_id?.trim() || null
|
||||
: controlAuthoritative ? state.device_session?.device_session_id ?? null : null,
|
||||
acquisitionId: acquisition?.acquisition_id ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function recoveryPresentationLease(
|
||||
authority: ActiveStreamRecoveryPresentationAuthority,
|
||||
): ObservationSourcePresentationLease {
|
||||
return {
|
||||
kind: "active-stream-recovery",
|
||||
runtimeId: authority.snapshotRuntimeId,
|
||||
acquisitionId: authority.acquisitionId,
|
||||
acquisitionStateRevision: authority.acquisitionStateRevision,
|
||||
producerGeneration: authority.runtimeProducerGeneration,
|
||||
recoveryGeneration: authority.recoveryGeneration,
|
||||
};
|
||||
}
|
||||
|
||||
function catalogDeclares(state: XgridsK1State, streamId: string): boolean {
|
||||
return Boolean(state.sensor_catalog?.streams?.some((stream) => stream.stream_id === streamId));
|
||||
}
|
||||
|
||||
function spatialAvailability(state: XgridsK1State): ObservationSourceAvailability {
|
||||
function spatialAvailability(
|
||||
state: XgridsK1State,
|
||||
recoveryAuthoritative: boolean,
|
||||
recoveryOwnsPresentation: boolean,
|
||||
): ObservationSourceAvailability {
|
||||
const mode = confirmedRuntimeSourceMode(state);
|
||||
if (mode !== "idle" && state.rerun_grpc_url?.trim()) return "streaming";
|
||||
if (state.rerun_grpc_url?.trim()) return "available";
|
||||
if (state.device_session?.connectivity === "degraded") return "degraded";
|
||||
if (state.device_session?.connectivity === "connected") return "available";
|
||||
return catalogDeclares(state, "spatial.point-cloud.live") ? "declared" : "unavailable";
|
||||
if (mode === "replay" && state.rerun_grpc_url?.trim()) return "streaming";
|
||||
const declared = catalogDeclares(state, "spatial.point-cloud.live");
|
||||
if (recoveryAuthoritative && state.rerun_grpc_url?.trim()) return "connecting";
|
||||
if (recoveryOwnsPresentation) return declared ? "degraded" : "unavailable";
|
||||
if (!hasControlAuthority(state)) return declared ? "unverified" : "unavailable";
|
||||
if (mode === "live" && state.rerun_grpc_url?.trim() && hasAuthoritativeData(state)) {
|
||||
return "streaming";
|
||||
}
|
||||
if (["stalled", "lost"].includes(
|
||||
state.connection_supervisor?.observed.data_plane.state ?? "idle",
|
||||
)) return "degraded";
|
||||
if (state.rerun_grpc_url?.trim() || declared) return "available";
|
||||
return "unavailable";
|
||||
}
|
||||
|
||||
function catalogAvailability(value: string | null | undefined): ObservationSourceAvailability {
|
||||
@@ -167,15 +222,42 @@ function browserDelivery(
|
||||
return { id, kind: value.kind, url, mediaType };
|
||||
}
|
||||
|
||||
function sameBrowserDelivery(
|
||||
left: ObservationSourceDelivery | null,
|
||||
right: ObservationSourceDelivery | null,
|
||||
): boolean {
|
||||
return Boolean(
|
||||
left
|
||||
&& right
|
||||
&& left.kind === "mse-fmp4-websocket"
|
||||
&& right.kind === "mse-fmp4-websocket"
|
||||
&& left.id === right.id
|
||||
&& left.url === right.url
|
||||
&& left.mediaType === right.mediaType,
|
||||
);
|
||||
}
|
||||
|
||||
function cameraAvailability(
|
||||
state: XgridsK1State,
|
||||
stream: XgridsSensorCatalogStream,
|
||||
selected: boolean,
|
||||
delivery: ObservationSourceDelivery | null,
|
||||
attested: boolean,
|
||||
recoverySelected: boolean,
|
||||
exactCurrentEpochReady: boolean,
|
||||
): ObservationSourceAvailability {
|
||||
if (recoverySelected) {
|
||||
return exactCurrentEpochReady
|
||||
? "streaming"
|
||||
: state.camera_preview?.phase?.trim().toLowerCase() === "degraded"
|
||||
? "degraded"
|
||||
: "connecting";
|
||||
}
|
||||
if (!attested) return "unverified";
|
||||
if (state.device_session?.connectivity === "degraded") return "degraded";
|
||||
if (!hasControlAuthority(state)) return "degraded";
|
||||
if (["stalled", "lost"].includes(
|
||||
state.connection_supervisor?.observed.data_plane.state ?? "idle",
|
||||
)) return "degraded";
|
||||
const base = catalogAvailability(stream.availability);
|
||||
if (!selected) return base === "streaming" || base === "connecting" ? "available" : base;
|
||||
|
||||
@@ -188,12 +270,82 @@ function cameraAvailability(
|
||||
return "connecting";
|
||||
}
|
||||
|
||||
function exactCurrentCameraEpochReady(state: XgridsK1State): boolean {
|
||||
const recovery = state.connection_recovery;
|
||||
const previewGeneration = state.camera_preview?.generation;
|
||||
if (
|
||||
!isXgridsActiveStreamRecovery(recovery)
|
||||
|| recovery.camera_media_state !== "ready"
|
||||
|| recovery.camera_media_ready !== true
|
||||
|| !Number.isInteger(previewGeneration)
|
||||
|| (previewGeneration ?? 0) < 1
|
||||
) return false;
|
||||
const epoch = recovery.camera_epoch;
|
||||
return Boolean(
|
||||
epoch
|
||||
&& epoch.generation === previewGeneration
|
||||
&& epoch.init_committed === true
|
||||
&& epoch.first_media_committed === true
|
||||
&& epoch.committed_media_segment_count > 0,
|
||||
);
|
||||
}
|
||||
|
||||
function recoveryCameraTupleIsExact(
|
||||
state: XgridsK1State,
|
||||
authority: ActiveStreamRecoveryPresentationAuthority | null,
|
||||
provider: ObservationSourceProvider,
|
||||
): boolean {
|
||||
const acquisition = state.acquisition;
|
||||
const deviceId = acquisition?.device_id?.trim();
|
||||
const deviceSessionId = acquisition?.device_session_id?.trim();
|
||||
const compatibilityProfileId = acquisition?.compatibility_profile_id?.trim();
|
||||
return Boolean(
|
||||
authority
|
||||
&& authority.recovery.camera_recovery === "owned"
|
||||
&& acquisition
|
||||
&& acquisition.acquisition_id.trim() === authority.acquisitionId
|
||||
&& deviceId
|
||||
&& deviceSessionId
|
||||
&& compatibilityProfileId
|
||||
&& state.device_ref?.device_id?.trim() === deviceId
|
||||
&& state.device_session?.device_session_id?.trim() === deviceSessionId
|
||||
&& state.device_session?.device_id?.trim() === deviceId
|
||||
&& state.device_session?.compatibility_profile_id?.trim() === compatibilityProfileId
|
||||
&& provider.compatibilityProfileId?.trim() === compatibilityProfileId
|
||||
);
|
||||
}
|
||||
|
||||
function cameraRecoveryPhaseRetainable(state: XgridsK1State): boolean {
|
||||
return [
|
||||
"active",
|
||||
"buffering",
|
||||
"connecting",
|
||||
"degraded",
|
||||
"ready",
|
||||
"reconnecting",
|
||||
"streaming",
|
||||
].includes(state.camera_preview?.phase?.trim().toLowerCase() ?? "");
|
||||
}
|
||||
|
||||
export function xgridsK1ObservationSources(
|
||||
state: XgridsK1State,
|
||||
activeModel: DeviceModelDefinition,
|
||||
): ObservationSourceDescriptor[] {
|
||||
const provider = providerFor(state, activeModel);
|
||||
const binding = bindingFor(state);
|
||||
const recoveryAuthority = activeStreamRecoveryPresentationAuthority(state);
|
||||
const recoveredBrowserAuthority = activeStreamRecoveredBrowserAuthority(state);
|
||||
const browserLineageAuthority = recoveryAuthority ?? recoveredBrowserAuthority;
|
||||
const recoveryOwnsPresentation = activeStreamRecoveryOwnsPresentationDecision(state);
|
||||
const recoveryAuthoritative = recoveryAuthority !== null;
|
||||
const presentationLease = browserLineageAuthority
|
||||
? recoveryPresentationLease(browserLineageAuthority)
|
||||
: null;
|
||||
const binding = bindingFor(state, browserLineageAuthority);
|
||||
const replayAuthoritative = state.source_mode === "replay";
|
||||
const dataAuthoritative = hasAuthoritativeData(state) && !recoveryOwnsPresentation;
|
||||
const spatialPreviewUrl = replayAuthoritative || dataAuthoritative || recoveryAuthoritative
|
||||
? state.rerun_grpc_url?.trim() || null
|
||||
: null;
|
||||
const clockId = binding.acquisitionId ?? binding.deviceSessionId ?? binding.deviceId ?? null;
|
||||
const descriptorId = (sourceId: string) =>
|
||||
`${provider.pluginId}:${provider.modelId}:${sourceId}`;
|
||||
@@ -205,12 +357,22 @@ export function xgridsK1ObservationSources(
|
||||
description: "Облако точек, поза и траектория в общей 3D-сцене",
|
||||
modality: "point-cloud",
|
||||
role: "primary",
|
||||
availability: spatialAvailability(state),
|
||||
availability: spatialAvailability(
|
||||
state,
|
||||
recoveryAuthoritative,
|
||||
recoveryOwnsPresentation,
|
||||
),
|
||||
transport: "rerun-grpc",
|
||||
endpointLabel: state.rerun_grpc_url?.trim() ? "Rerun gRPC" : "MQTT → Rerun",
|
||||
previewUrl: state.rerun_grpc_url?.trim() || null,
|
||||
previewUrl: spatialPreviewUrl,
|
||||
delivery: null,
|
||||
activation: null,
|
||||
presentationLease: (
|
||||
recoveryAuthoritative
|
||||
|| (recoveredBrowserAuthority !== null && dataAuthoritative)
|
||||
) && spatialPreviewUrl
|
||||
? presentationLease
|
||||
: null,
|
||||
provider,
|
||||
binding,
|
||||
capabilities: {
|
||||
@@ -234,9 +396,27 @@ export function xgridsK1ObservationSources(
|
||||
const sourceId = stream.source_id?.trim();
|
||||
if (sourceId) sourceIdCounts.set(sourceId, (sourceIdCounts.get(sourceId) ?? 0) + 1);
|
||||
}
|
||||
const attested = Boolean(provider.compatibilityProfileId && binding.deviceSessionId);
|
||||
const supervisor = state.connection_supervisor;
|
||||
const verifiedControl = state.application_control_session?.verified_control;
|
||||
const attested = Boolean(
|
||||
hasControlAuthority(state)
|
||||
&& provider.compatibilityProfileId
|
||||
&& binding.deviceSessionId
|
||||
&& verifiedControl
|
||||
&& supervisor?.observed.control_plane.session_id === verifiedControl.control_session_id
|
||||
&& supervisor.observed.device_identity.logical_device_id
|
||||
=== verifiedControl.logical_device_id
|
||||
&& supervisor.observed.device_identity.compatibility_profile_id
|
||||
=== verifiedControl.compatibility_profile_id,
|
||||
);
|
||||
const sessionScope = binding.deviceSessionId ?? binding.deviceId ?? "unbound";
|
||||
const activeSourceId = state.camera_preview?.active_source_id?.trim() ?? null;
|
||||
const exactCameraMediaReady = exactCurrentCameraEpochReady(state);
|
||||
const browserLineageCameraTupleExact = recoveryCameraTupleIsExact(
|
||||
state,
|
||||
browserLineageAuthority,
|
||||
provider,
|
||||
);
|
||||
|
||||
const cameras = cameraRows.flatMap<ObservationSourceDescriptor>((stream) => {
|
||||
const sourceId = stream.source_id?.trim();
|
||||
@@ -249,19 +429,58 @@ export function xgridsK1ObservationSources(
|
||||
const activationValid = Boolean(
|
||||
groupId && Number.isInteger(maxActive) && (maxActive ?? 0) > 0,
|
||||
);
|
||||
const selected = Boolean(
|
||||
attested && activationValid && rawActivation?.selected === true && activeSourceId === sourceId,
|
||||
const normallySelected = Boolean(
|
||||
!recoveryOwnsPresentation
|
||||
&& attested
|
||||
&& activationValid
|
||||
&& rawActivation?.selected === true
|
||||
&& activeSourceId === sourceId
|
||||
&& exactCameraMediaReady,
|
||||
);
|
||||
const streamDelivery = browserDelivery(stream.delivery);
|
||||
const previewDelivery = browserDelivery(state.camera_preview?.delivery);
|
||||
const candidateDelivery = stream.delivery ?? state.camera_preview?.delivery;
|
||||
const retainedDelivery = browserDelivery(candidateDelivery);
|
||||
const deliveryConsistent = !stream.delivery || !state.camera_preview?.delivery
|
||||
|| sameBrowserDelivery(streamDelivery, previewDelivery);
|
||||
const streamRecoveryAvailable = [
|
||||
"available",
|
||||
"connecting",
|
||||
"degraded",
|
||||
"streaming",
|
||||
].includes(catalogAvailability(stream.availability));
|
||||
const browserLineageSelected = Boolean(
|
||||
browserLineageCameraTupleExact
|
||||
&& activationValid
|
||||
&& maxActive === 1
|
||||
&& rawActivation?.selected === true
|
||||
&& activeSourceId === sourceId
|
||||
&& cameraRecoveryPhaseRetainable(state)
|
||||
&& streamRecoveryAvailable
|
||||
&& retainedDelivery
|
||||
&& deliveryConsistent
|
||||
);
|
||||
const recoverySelected = recoveryAuthority !== null && browserLineageSelected;
|
||||
const recoveredBrowserSelected = Boolean(
|
||||
recoveredBrowserAuthority
|
||||
&& browserLineageSelected
|
||||
);
|
||||
const selected = normallySelected || recoverySelected || recoveredBrowserSelected;
|
||||
const activation = activationValid
|
||||
? {
|
||||
groupId: `${provider.pluginId}:${sessionScope}:${groupId}`,
|
||||
maxActive: maxActive as number,
|
||||
selected,
|
||||
controllable: Boolean(attested && rawActivation?.controllable),
|
||||
controllable: Boolean(
|
||||
!recoveryOwnsPresentation && attested && rawActivation?.controllable,
|
||||
),
|
||||
}
|
||||
: null;
|
||||
const candidateDelivery = stream.delivery ?? state.camera_preview?.delivery;
|
||||
const delivery = selected ? browserDelivery(candidateDelivery) : null;
|
||||
const delivery = selected && (
|
||||
dataAuthoritative || recoverySelected || recoveredBrowserSelected
|
||||
)
|
||||
? retainedDelivery
|
||||
: null;
|
||||
const label = stream.label?.trim() || sourceId;
|
||||
|
||||
return [{
|
||||
@@ -272,12 +491,23 @@ export function xgridsK1ObservationSources(
|
||||
description: "Видеоканал, опубликованный активным device-плагином",
|
||||
modality: "video",
|
||||
role: "auxiliary",
|
||||
availability: cameraAvailability(state, stream, selected, delivery, attested),
|
||||
availability: cameraAvailability(
|
||||
state,
|
||||
stream,
|
||||
selected,
|
||||
delivery,
|
||||
attested,
|
||||
recoverySelected || recoveredBrowserSelected,
|
||||
exactCameraMediaReady,
|
||||
),
|
||||
transport: delivery ? "websocket" : "other",
|
||||
endpointLabel: safeEndpointLabel(stream.endpoint_label) ?? "Локальный video adapter",
|
||||
previewUrl: null,
|
||||
delivery,
|
||||
activation,
|
||||
presentationLease: (recoverySelected || recoveredBrowserSelected) && delivery
|
||||
? presentationLease
|
||||
: null,
|
||||
provider,
|
||||
binding,
|
||||
capabilities: {
|
||||
|
||||
Reference in New Issue
Block a user