Skip to content

Latest commit

 

History

History
59 lines (44 loc) · 2.02 KB

File metadata and controls

59 lines (44 loc) · 2.02 KB

Cardinal wire protocol (Phase 1)

The Go control plane talks to the C++ engine (carded) over a Unix domain socket using a small framed binary protocol. All multi-byte integers are little-endian. Floats are IEEE-754 binary64 (Go math.Float64bits / C++ memcpy-bitcast).

Framing

Every request and response is a single frame:

[u32 length][payload]      // length excludes the 4-byte prefix; max 64 MiB
  • Request payload: [u8 op][body]
  • Response payload: [u8 status][body]status == 0 is OK.

Operations

op name request body response body
0 Ping (none) (none)
1 Write u32 count, then count × {u64 series_id, i64 ts_ms, f64 value} u64 accepted
2 Query u64 series_id, i64 start_ms, i64 end_ms, u8 agg see below
3 Stats (none) u64 series, u64 samples, u64 chunks, u64 chunk_bytes

Aggregation codes (agg)

code meaning
0 Raw (return points)
1 Sum
2 Min
3 Max
4 Avg
5 Count
6 Rate (per-second, over the window)

Query response body

  • Raw (agg == 0): u32 count, then count × {i64 ts_ms, f64 value}.
  • Aggregation (agg != 0): u8 has_scalar, then f64 scalar (has_scalar == 0 means the series/range was empty).

Series identity

series_id = FNV-64a(metric, sorted(labels)), computed in the control plane (engineclient.SeriesID). Labels are sorted before hashing so the id is independent of map/iteration order — this is what makes routing the same series to the same shard deterministic across nodes.

Notes / roadmap

  • This protocol is the Phase-1 transport. The ingest fast path is slated to move to a shared-memory ring buffer (the engine and control plane already run on the same host and share a socket today); query/admin stay here.
  • A real deployment would add per-request ids, a protocol version byte, and optional batching of query results into time-bucketed pages.