Distribution, Robotics & GPU tail (EG-3.x)¶
The last engine features of Program B, closing the distribution / robotics / GPU tail. Every
one is feature-gated into the opt-in full-extras layer — the heavy deps (cudarc,
rustdds, tokio-tungstenite) are optional and the main/default build links none of them
(cargo tree -i cudarc / -i rustdds on the default build is empty). This page documents the four subsystems and their control/data flow.
| Feature | Concept | Module | Feature flag |
|---|---|---|---|
| Cross-region async read-replica tier | CONCEPT:EG-KG.sharding.follower-pull-loop |
src/server/replica.rs |
federation-search |
| Capacity guardrails (breaker/quota/backpressure) | CONCEPT:EG-KG.coordination.circuit-breaker |
src/server/replica.rs |
federation-search |
| Full Calvin deterministic-ordering commit | CONCEPT:EG-KG.txn.calvin-deterministic-ordering |
src/raft/cross_shard_txn.rs |
calvin (⇒ nonblocking) |
| ROS2 bridge over rosbridge-WebSocket | CONCEPT:EG-KG.domains.robotics-gpu-distribution |
src/server/ros2_bridge.rs |
ros2-bridge |
| GPU distance/tensor dispatch seam | CONCEPT:EG-KG.compute.gpu-distance-seam |
crates/eg-ann/src/distance.rs, crates/eg-tensor/src/gpu.rs |
gpu |
| Real CUDA distance/tensor backend | CONCEPT:EG-KG.backend.real-cuda-tensor-backend |
same | gpu-cuda |
Cross-region async read-replica tier + guardrails (EG-322 / EG-323)¶
Beyond the synchronous multi-Raft groups + the EG-KG.ontology.federation-client federated read, a distant region gets
a local, eventually-consistent read copy that never pays a cross-region Raft round-trip on
every write. The primary appends every committed mutation to a bounded monotone-LSN
ReplicationLog and serves the tail over /replicate?since=<lsn>; a follower pulls it and
applies it via the canonical wal::apply path (byte-identical to Raft/WAL replay). Capacity
guardrails — a circuit breaker, a per-tenant quota, and backpressure — protect the primary from
a slow/hostile region or a greedy tenant.
flowchart LR
subgraph Primary [Primary region]
W[dispatch commit] -->|append LSN| LOG[(ReplicationLog\nbounded ring)]
LOG --> SRV["/replicate?since=n serve"]
end
subgraph Follower [Follower region — read replica]
CB{CircuitBreaker\nallow?}
PULL[run_replica_follower\npull loop] --> CB
CB -->|closed / half-open| SRV
SRV -->|ordered tail| APPLY[apply_replicated_batch\nwal::apply]
APPLY --> REG[(local registry\nread-serve)]
CB -->|open: fail fast| SKIP[skip tick]
end
CLIENT[Local reads] --> REG
subgraph Guards [EG-323 capacity guardrails]
G[CapacityGuard\nper-tenant quota + backpressure]
end
REQ[Requests] --> G -->|Admit / Quota / Backpressure| REG
ReplicationLog::since(cursor)returns the ordered ops after the cursor and aReplicaLag: a follower whose cursor predates the retained ring is toldBehind(re-snapshot) rather than silently skipping ops.CircuitBreakeris a pure Closed→Open→HalfOpen state machine driven by an explicitnow: Instant(deterministically testable): it opens after N consecutive failures for a cooldown, then admits one half-open trial whose outcome closes or re-opens it.CapacityGuardenforces a per-tenant hard concurrency quota (QuotaExceeded) and a global high-water backpressure shed (Backpressure), complementing the EG-320 QoS scheduler's priority reordering with absolute ceilings.
Enabled by EPISTEMIC_GRAPH_REPLICATE=1 (primary log) + EPISTEMIC_GRAPH_REPLICA_PRIMARY=<url>
(follower). Off by default — a non-replicated primary pays nothing.
Full Calvin deterministic-ordering commit (EG-KG.txn.calvin-deterministic-ordering)¶
A third cross-shard commit branch alongside 2PC (commit_cross_shard) and Paxos-Commit-lite
(commit_cross_shard_nonblocking). Where those are agreement-first (every writing participant
runs an OCC prepare and VOTES), Calvin is order-first: a global CalvinSequencer stamps the txn
with a monotone total-order GlobalSeq, that ORDER is Raft-replicated (the "input log"), and
participants EXECUTE it deterministically with no vote round and no abort. Agreement on the
order IS agreement on the outcome, so a crashed coordinator is resolved by any node replaying the
replicated sequence — there is no in-doubt window.
sequenceDiagram
participant C as Coordinator
participant S as CalvinSequencer
participant D as Decision Raft group
participant P as Participant groups
C->>S: assign() → GlobalSeq
Note over C,S: deterministic_order() gives ANY node the same total order
C->>D: replicate_sequence(txn, seq) (the atomic point)
D-->>C: quorum-committed + applied (readable on every replica)
C->>P: apply_sequenced (GroupId order, NO vote / NO prepare)
C->>D: clear_replicated_decision (GC)
Note over C,P: Crash after replicate_sequence? recover_sequenced() on ANY node<br/>learns the seq and REPLAYS to completion — no blocking window
Opt-in per call via the calvin feature (implies nonblocking to reuse the EG-KG.txn.harness-crash replicated
decision-graph helpers); the default cross-shard path is byte-for-byte unchanged. Honest
scope: the sequencer + total order + replicated input log + vote-free deterministic execution +
crash-replay recovery are implemented and proven (live calvin_* harness tests). The distributed
OLLP reconnaissance/read-lock phase (full serializable isolation of conflicting sequenced txns
across nodes) and a multi-node sequencer epoch fan-in are documented-deferred — additive, and they
weaken no shipped invariant.
ROS2 bridge over rosbridge-WebSocket (EG-KG.domains.robotics-gpu-distribution)¶
Joins a ROS2 graph WITHOUT a DDS stack by speaking the standard rosbridge_suite protocol —
JSON messages over a WebSocket to a rosbridge_server. No CycloneDDS/rmw/ros C toolchain — a
pure-Rust tokio-tungstenite client.
flowchart LR
subgraph Engine
CDC[(CDC feed)] --> C2P[cdc_to_publish]
P2M[publish_to_method] --> APPLY[wal::apply → graph]
end
subgraph WS [rosbridge WebSocket]
C2P -->|op:publish| RB[rosbridge_server]
RB -->|op:publish inbound| P2M
ADV[op:advertise] --> RB
SUB[op:subscribe] --> RB
end
RB <--> ROS[ROS2 nodes / topics]
- Engine → ROS2: tail the CDC feed for a graph; each change becomes a rosbridge
{"op":"publish","topic":…,"msg":{"data":…}}(cdc_to_publish). - ROS2 → engine:
subscribea topic; each inbound publish maps to anAddNode(publish_to_method) applied viawal::apply.
The protocol framing (RosbridgeOp) + the CDC↔ROS2 mapping are pure and unit-tested; the
WebSocket driver (run_ros2_bridge) wires them onto a live connection. Enabled by
EPISTEMIC_GRAPH_ROSBRIDGE_URL=ws://host:9090.
Two further legs sit behind the SAME DdsTransport trait (src/server/dds.rs), both
full-extras-only (never in default/full):
ros2-dds— a native DDS/RTPS wire over the PURE-RUSTrustddscrate (mio/pnet/speedy/cdr-encoding). No CycloneDDS/rmw/C toolchain, so it CI-builds everywhere; wire-compatible with the rmw name/type mangling (below) but not the CycloneDDS-C stack itself.ros2-rmw(S5) — the REALrmw_cyclonedds/CycloneDDS-C stack via the safecycloneddsRust crate.cyclonedds-srcvendors the CycloneDDS C sources IN the crate tarball (no network fetch at build time);cyclonedds-rust-sys's build.rs configures + builds it withcmake(static lib) and ships prebuilt bindgen output, so it needs a C toolchain (cc/cmake) but not libclang at build time. This is genuine zero-config live-ros2interop — a realros2node discovers/pubs/subs with no bridge.
Both legs apply the rmw name/type mangling convention (mangle_topic_name/
mangle_type_name in src/server/dds.rs, CONCEPT:EG-KG.ingest.rmw-topic-prefix) so a
topic published either way is discoverable by a live ros2 daemon with zero config: the
rt/ topic prefix + the <pkg>::<ns>::dds_::<Msg>_ type descriptor. Neither leg is
folded into the workspace --all-features build (toolchain-gated, full-extras opt-in
only).
GPU distance/tensor dispatch seam + CUDA backend (EG-KG.compute.gpu-distance-seam / EG-KG.backend.real-cuda-tensor-backend)¶
Vector search and tensor ops are dominated by one embarrassingly-parallel kernel each (batch distance; elementwise map). Both are factored behind a backend trait so the compute device is swappable WITHOUT touching the index/tensor code. The pure-Rust CPU backend is ALWAYS compiled in and is the byte-for-byte ground truth; the real CUDA backend is selected only when built AND a device initialises.
flowchart TD
SEARCH["FlatIndex::search / Tensor::elementwise"] --> DISPATCH["batch_distances / elementwise_dispatch"]
DISPATCH --> ACTIVE{active_backend}
ACTIVE -->|gpu-cuda built + device present| CUDA[CudaBackend\nNVRTC kernel launch]
ACTIVE -->|else / no device / launch error| CPU[CpuBackend\npure-Rust, ground truth]
CUDA -.transient failure.-> CPU
DistanceBackend(eg-ann) /TensorBackend(eg-tensor):batch_distance/elementwiseover a flat buffer. Every backend must agree with the CPU backend to within floating-point tolerance, so GPU and CPU results are interchangeable.CudaBackend(featuregpu-cuda): NVRTC-compiles the CUDA-C kernel at first use, ships buffers to the device, launches one thread per row/element, copies scores back.cudarcisdynamic-loading— libcuda/libnvrtc are dlopen'd at runtime — so the leg builds with no CUDA toolkit and, on a GPU-less host,active_backendreturns the CPU backend (fully functional).
Invariant: the seam is pure-Rust; gpu/gpu-cuda are OUT of the main build (full-extras-only),
and cudarc links only under gpu-cuda. Deferred: live validation of the kernels on real GPU
hardware (none in CI) and GPU offload of reasoning / ANN build beyond the distance/elementwise
kernels.
See also: Capabilities matrix · Numeric Kernel · Engine Scaling Program · Multi-Raft Cluster Status · Agent Memory.