Skip to content

04. Streaming, Backpressure, and UI Responsiveness

Why This Topic Matters

The repo is not only orchestrating machine commands. It is also consuming ongoing data streams:

  • telemetry
  • preview frames

That makes the system a good place to teach a practical runtime truth:

  • if producers are faster than consumers, you need a policy

The app does not pretend that every streamed item must be preserved forever. Instead, it uses bounded pipelines and makes drop or coalescing behavior visible.

Telemetry Policy

Telemetry consumption is handled by:

  • src/InspectionPrototype.Application/Services/TelemetryPipelineService.cs

The service documents a clear policy:

  • channel capacity is 1
  • lag policy uses DropOldest
  • stale telemetry snapshots may be coalesced
  • coalescing is recorded in counters and diagnostics

This design favors freshness over historical completeness.

That is usually the right choice for operator telemetry. A fresh value is more useful than a queue of outdated readings.

Frame Policy

Frame consumption is handled by:

  • src/InspectionPrototype.Application/Services/FramePipelineService.cs

The frame pipeline uses:

  • channel capacity 3
  • DropOldest
  • frame-drop counters and diagnostics

This means the preview prioritizes recent frames instead of preserving a stale backlog.

The frame pipeline also runs simple fake defect detection for active runs, which makes it a good example of background consumption plus runtime mutation.

Why Visibility Matters

One of the better teaching choices in the repo is that these policies are not hidden.

The runtime exposes:

  • telemetry coalescing
  • frame drops
  • diagnostics entries for pipeline lag

That makes backpressure visible enough for a learner to observe and reason about.

UI Responsiveness

The presentation layer still needs to remain responsive while all this background activity is happening.

MainViewModel handles that by:

  • subscribing to IAppStateStore.StateChanged
  • marshaling updates onto the WPF dispatcher thread
  • projecting state into UI-friendly fields

This is a critical rule:

  • background services may publish state from non-UI threads
  • the view model is responsible for safe UI-thread projection

Avoiding Projection Churn

The view model also avoids rebuilding certain collections on every state change:

  • recipe catalog
  • run history
  • diagnostics
  • simulator profile catalog

This is a subtle performance lesson. Even if the architecture is correct, careless projection churn can still damage perceived responsiveness.

Trade-Offs

Benefits

  • bounded memory behavior
  • observable backpressure trade-offs
  • more realistic operator-facing freshness policy
  • safer UI-thread interaction

Costs

  • not every telemetry or frame item is preserved
  • the learner must understand that dropping or coalescing can be intentional, not automatically a bug

Diagram Brief

  • Title: Streaming, backpressure, and UI projection
  • Purpose: Show how telemetry and frame producers flow through bounded pipelines into canonical state and then into the WPF UI
  • Audience: newcomer developer learning runtime data-flow trade-offs
  • Nodes: Telemetry Source, Frame Source, TelemetryPipelineService, FramePipelineService, AppStateStore, AppState, MainViewModel, WPF Dispatcher, UI Panels
  • Edges: sources feed pipelines; pipelines update canonical state; state changes are dispatched through MainViewModel to the UI; counters and diagnostics expose coalescing and drops
  • Grouping: Background producers, pipeline consumers, state owner, UI projection
  • Caption: Responsiveness comes from bounded pipelines plus safe UI-thread projection, not from pretending all producers and consumers run at the same speed
  • Destination file path: docs/diagrams/source/course-04-04-streaming-backpressure-and-ui-responsiveness.drawio

Docs-first project memory for AI-assisted implementation.