Developer Guide
Bounded context: Telemetry Distribution · Stack: Rust / Axum · Code-level walkthrough: Contracts Service
The contracts-service realises the Telemetry Distribution context. It sits between the raw reading stream and the browser feed, routing each reading to its building’s live feed. It is the one service written in Rust, chosen for throughput on a hot path that inspects every reading.
There isn’t a named pattern here worth reaching for — it’s two Tokio tasks in one process, sharing one piece of state. AppState (state.rs) is exactly two fields: Arc<DashMap<String, Vec<String>>> mapping a building ID to its allowed metric keys, and a handle to the MongoDB preferences collection. The Axum HTTP server (api/) reads and writes that map when preferences change; the background task (tunnel.rs) reads it on every single incoming reading, to decide what to keep. Both hold a clone of the same Arc, so a preference change made through the API is visible to the very next reading the tunnel processes — DashMap gives lock-free concurrent reads, so that visibility doesn’t cost a database round trip.
graph TD
subgraph "HTTP — api/"
DASH["dashboard.rs: get_dashboard_tables"]
DATA["data.rs: get_preferences, update_preferences"]
INIT["init.rs: init_building_preferences"]
end
subgraph "Background worker — tunnel.rs"
TUNNEL["reads the raw-reading broker,\nfilters each event through AppState,\nrepublishes per building"]
end
subgraph "Shared state — state.rs"
CACHE["AppState:\nDashMap (buildingId to allowedMetricKeys)\n+ Mongo collection handle"]
end
subgraph "infra/"
DBMOD["db.rs"]
DISC["discovery.rs — catalog gathering"]
MET["metrics.rs"]
end
DATA --> CACHE
INIT --> CACHE
TUNNEL --> CACHE
DASH --> DISC
CACHE -.-> DBMOD
DBMOD -.-> MONGO[(MongoDB)]
BR1[(broker: raw readings)] --> TUNNEL
TUNNEL --> BR2[(broker: per-building feeds)]buildingId — one O(1) lookup, never a cross-building fan-out. Metric type is not gated: the dashboard’s column preferences are display-only and no longer decide what telemetry flows, so views like the 3D model stay live regardless of the table’s columns.api/ and tunnel.rs never talk to each other directly — the only thing they share is a clone of the same AppState. Neither knows the other exists.For the concurrency model, the tunnel internals, persistence status, and the API, see the Contracts Service internals page.