Skip to content

WebSocket Telemetry Stream Frame Desync in Canvas Real-Time Resource Chart #44

Description

@elizabetheonoja-art

WebSocket Telemetry Stream Frame Desync in Canvas Real-Time Resource Chart

Problem Statement

The real-time resource consumption chart in src/components/dashboard/ResourceTelemetryChart.tsx renders streaming telemetry as a multi-line SVG/Canvas chart using Chart.js with a streaming plugin. The WebSocket handler at src/hooks/useTelemetryStream.ts:55 receives binary-framed telemetry messages, parses them, and pushes data points to the chart's data store via chartRef.current.data.datasets[i].data.push(). The WebSocket connection uses a custom binary framing protocol (sequence number + payload) but the sequence number validation at src/utils/telemetry/frameValidator.ts:30 only checks for gaps > 1 (i.e., dropped frames), not for frame reordering. When the WebSocket reconnects after a brief network interruption (common in mobile DePIN deployments), the new stream's sequence counter resets to 0. The validator sees lastSequence = 5201 followed by newSequence = 3 and treats it as a drop of 5198 frames, not recognizing the counter reset. The chart data store receives 5198 synthetic "gap-fill" null data points, causing the canvas to render a flat horizontal line across the chart for 86 seconds at 60fps (5198 / 60 ≈ 86s), during which all real telemetry is visually suppressed.

State Invariants & Parameters

  • Sequence number: u16 (wraps at 65535)
  • Max sequence gap before reset detection: 1000 frames
  • Reconnect behavior: new TCP connection, counter resets to 0
  • Chart data store: Chart.js reactive array (max 10,000 points)
  • Gap-fill behavior: insert null for each missing sequence
  • Frame rate: 60 updates/s (WebSocket batch)
  • Invariant: chart_data.length == elapsed_time * 60 (no synthetic insertion)

Affected Code Paths

  • src/hooks/useTelemetryStream.ts:50-100 — WebSocket message handler pushing to chart
  • src/utils/telemetry/frameValidator.ts:25-55 — Sequence checking with no reset detection
  • src/components/dashboard/ResourceTelemetryChart.tsx:60-110 — Chart component rendering null data points
  • src/hooks/tests/useTelemetryStream.test.ts — No reconnection-with-reset test

Resolution Blueprint

  1. Implement stream epoch detection in frameValidator.ts: newConnection flag is set on WebSocket onopen. On the first message after reconnection, the validator accepts any sequence number (skipping gap check for the first frame of a new connection epoch). The epoch is identified by a monotonic connectionId (UUID per onopen event).
  2. Replace null gap-fill with decimated interpolation: instead of inserting nulls, compute (prevValue + nextValue) / 2 for each missing point and fill with interpolated values. Mark interpolated points with a synthetic: true flag so they can be rendered with dashed lines or lower opacity.
  3. Cap the maximum gap-fill window to 300 frames (5 seconds at 60fps). If the gap exceeds 300, insert a NaN sentinel that the chart renderer treats as a gap separator (disconnected line segments). The 300-frame cap prevents the chart from freezing for 86s.
  4. Add a SequenceTracker class that maintains a sliding window of the last 100 sequence numbers. On reconnect, it learns the new baseline within 100 frames and adapts. Gap detection uses median-absolute-deviation (MAD) from the window rather than raw subtraction.
  5. Add a benchmark test in tests/benchmarks/telemetry_chart_reconnect.ts that simulates 10 reconnection cycles with counter resets, measuring the time until the chart displays live data again (target: < 500ms).

Labels

  • Complexity: Hardcore
  • Layer: Core-Engine
  • Type: Race-Condition

Metadata

Metadata

Labels

Complexity: HardcoreIssues requiring deep systems-level engineering rigorGrantFox OSSIssue tracked in GrantFox OSSLayer: Core-EngineCore engine layerMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignType: Race-ConditionConcurrency and race condition related issues

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions