Ternary service registry for GPU fleets. Nodes register their capabilities, clients discover services by capability, and a CRDT merge protocol keeps registries synchronized across instances.
Distributed GPU fleets need a way to track which compute nodes are available, what each node can do, and whether each node is healthy. This crate provides a simple, in-memory registry that answers three questions:
- Discovery: which nodes can serve a given capability?
- Health filtering: which of those nodes are healthy enough to use?
- Synchronization: how do we merge registries from different instances?
Health is modeled as a ternary value — healthy (1), degraded (0), failed (−1) — matching the ternary computing model used across the SuperInstance ecosystem.
| Type | Meaning |
|---|---|
Health |
Ternary health status: Healthy (1), Degraded (0), Failed (−1) |
ServiceNode |
A registered compute node with capabilities, health, load, and version |
ServiceRegistry |
Central registry: register, discover, and merge nodes |
| State | Discoverable? | Load-balanced? |
|---|---|---|
Healthy |
Yes | Yes (discover_least_loaded) |
Degraded |
Yes | No (excluded from discover_healthy) |
Failed |
No | No |
# Cargo.toml
[dependencies]
ternary-registry = "0.1"use ternary_registry::{Health, ServiceNode, ServiceRegistry};
fn main() {
let mut reg = ServiceRegistry::new();
// Register nodes with capabilities
reg.register(ServiceNode::new("gpu-0", vec!["matmul", "attention"]));
reg.register(ServiceNode::new("gpu-1", vec!["matmul", "filter"]));
// Discover all non-failed nodes for a capability
let nodes = reg.discover("matmul");
println!("matmul nodes: {}", nodes.len()); // 2
// Mark a node as failed — it disappears from discovery
reg.update_health("gpu-0", Health::Failed);
let healthy = reg.discover("matmul");
println!("healthy matmul nodes: {}", healthy.len()); // 1
// Find the least-loaded healthy node for load balancing
reg.update_load("gpu-1", 0.42);
if let Some(best) = reg.discover_least_loaded("matmul") {
println!("least loaded: {}", best.id); // gpu-1
}
}register(node)— add or replace a node (duplicates by ID are handled cleanly)deregister(id)— remove a node and prune its capability index entriesdiscover(capability)— all non-failed nodes with the given capabilitydiscover_healthy(capability)— onlyHealthynodes (subset ofdiscover)discover_least_loaded(capability)— theHealthynode with the lowest loadupdate_health(id, health)— change a node's health statusupdate_load(id, load)— change a node's load valuecrdt_merge(other)— merge another registry's nodes into this onenode_count(),healthy_count(),service_count()— registry statistics
The crdt_merge method propagates failures monotonically: if any replica
marks a node as Failed, all replicas converge to Failed after merging.
Nodes that exist only in the source registry are added. Non-failed health
states are not overwritten, ensuring merge is idempotent and commutative with
respect to the failure-propagation semilattice.
new(id, capabilities)— create a node (defaults:Healthy, load0.0)- Fields:
id,capabilities,health,load,version(all public)
- In-memory only: no persistence layer. State is lost on restart.
- No concurrent access:
ServiceRegistryis notSync. Wrap inArc<Mutex<_>>for multi-threaded use. - Linear discovery:
discoverscans the capability index vector. Fine for dozens to hundreds of nodes; not indexed for thousands. - CRDT merge propagates failures only: degraded/healthy states from the remote registry do not overwrite local state. This is intentional — failures are the only monotonic signal.
- No version negotiation: the
versionfield is stored but not used for compatibility checks.
Part of the SuperInstance ternary computing ecosystem:
ternary— core trit types and balanced ternary arithmeticternary-registry— this crateternary-constraint— constraint satisfaction for ternary variablesternary-control— ternary control theoryternary-sensor— sensor classification and fusion
MIT