embedded_single_node
Source:
crates/dynomite/examples/embedded_single_node.rs --
run with cargo run -p dynomite --example embedded_single_node
(requires a Valkey/Redis on 127.0.0.1:6379)
What it demonstrates
The full ServerBuilder chain for a realistic single node: a named
pool, both listeners, a Valkey backend, datacenter and rack identity, a
token, a request timeout, and gossip explicitly disabled.
#![allow(unused)]
fn main() {
use std::time::Duration;
use dynomite::conf::{ConfServer, DataStore};
use dynomite::embed::{Server, ServerBuilder};
let server: Server = ServerBuilder::new("dyn_o_mite")
.listen("127.0.0.1:18102".parse()?)
.dyn_listen("127.0.0.1:18101".parse()?)
.data_store(DataStore::Valkey)
.servers(vec![ConfServer::parse("127.0.0.1:6379:1 backend")?])
.datacenter("dc-local")
.rack("rack-local")
.tokens_str("0")
.timeout(Duration::from_secs(5))
.enable_gossip(false)
.build()?;
let handle = server.start().await?;
}
Note the two-step build/start here, in contrast to
embedded_minimal’s start_with. The Server
value exists before it starts, which is the seam you use to wire up
observability.
The example then reads a stats snapshot and shuts down, rather than
blocking on Ctrl-C, so it terminates cleanly under cargo run:
#![allow(unused)]
fn main() {
let snap = handle.stats();
eprintln!("snapshot pool={} uptime={}s", snap.pool.name, snap.uptime);
handle.shutdown().await?;
}
The configuration, knob by knob
data_store(DataStore::Valkey)- Selects the RESP/Valkey backend protocol. See Redis / Valkey.
servers(["127.0.0.1:6379:1 backend"])- The backing store endpoint and weight; parsed by
ConfServer::parse. The trailing name is a label. datacenter/rack- This node's placement in the topology. Even a single node has a DC and rack because the consistency and replication logic is defined in those terms; see Replication and Consistency.
tokens_str("0")- The token this node owns on the ring. A lone node owns the whole ring, so any single token works; see The Ring.
enable_gossip(false)- There are no peers, so gossip has nothing to do. Turning it off keeps startup instant and the log quiet.
Design decisions and trade-offs
Note
Road not taken: implicit topology
The builder does not infer datacenter, rack, or token. Dynomite makes placement explicit because getting it wrong silently changes where data lands – an implicit default would hide a decision that has to be deliberate in any real cluster. The cost is a little more ceremony for a single node; the benefit is that the single-node config reads the same as a production one.
Fronting an existing Valkey (rather than the in-memory default) is the point of this example: it shows that the engine’s job is orchestration, not storage. The backing store stays a plain Valkey that knows nothing about the ring.
When to use this pattern
As the starting point for any single-node embedding that fronts a real
store, and as the template you extend by adding peers (see
embedded_cluster3) and hooks (see
Hooks and Traits).
Where to go next
embedded_cluster3turns this into three cooperating nodes with a customDatastore.- Configuration is the full reference for every knob shown here and many more.