Skip to main content

Runtime

Struct Runtime 

Source
pub struct Runtime<C: Commands> { /* private fields */ }
Expand description

The public entry point: configure and run the thread-per-core server.

Implementations§

Source§

impl<C: Commands> Runtime<C>

Source

pub fn builder(commands: C) -> Self

Start configuring a runtime for commands. Runtime is its own builder: chain Self::bind / Self::shards / the with_* setters, then call run. Defaults: bind 127.0.0.1:6004, one shard, AOF on (EverySec), data dir ".".

Source

pub fn bind(self, ip: [u8; 4], port: u16) -> Self

Listen address for the client TCP listener (every shard binds it via SO_REUSEPORT). Default 127.0.0.1:6004.

Source

pub fn shards(self, n: usize) -> Self

Shard (reactor thread) count. Clamped to at least 1. Default 1.

Source

pub fn with_unix_socket(self, path: PathBuf) -> Self

Spawn one thread per shard and run until stop is set. UDS: also bind a Unix-domain stream listener at path. Lets local clients (and benchmarks) skip the TCP loopback round-trip. Bound on shard 0 only (no SO_REUSEPORT for AF_UNIX, single global socket like valkey’s unixsocket config). TCP listener stays bound at the configured port regardless.

Source§

impl<C: Commands> Runtime<C>

Source

pub fn with_replication(self, enabled: bool, buffer_size: u64) -> Self

v3-cluster replication producer side: when enabled, each shard runs a per-shard ReplicationSource with buffer_size byte budget. Every applied mutation is pushed to the backlog for connected replicas to consume. enabled = false (default) is zero hot-path cost — each write checks Option::is_some() and skips. The replication TCP listener / streaming loop are gated separately by Self::with_replication_listener; enabling the producer without a listener means the backlog fills and frames are dropped per the source’s eviction policy, but writes proceed normally.

Source

pub fn with_feed(self, enabled: bool, buffer_size: u64) -> Self

Enable the FEED.* consumer surface. Keeps a per-shard backlog (even with no replicas) and persists the (generation, offset) cursor via the feed sidecars. buffer_size = 0 keeps the default (64 MB/shard); effective budget is max(replication_buffer_size, feed_buffer_size) when both features are on.

Source

pub fn with_replication_listener(self, port_base: u16) -> Self

Bring up a replication listener per shard at port_base + shard_id (per Issue Ledger I2 — mirrors the cluster listener pattern). Replica clients connect to each per-shard port to mirror the full keyspace. This is independent of Self::with_replication: a primary that runs the producer backlog without a listener (benchmarks, embed-only) is supported.

Source

pub fn with_replication_reconnect_window(self, ms: u32) -> Self

Per-shard SlotTable reconnect window in milliseconds — the grace period a disconnected replica’s slot is retained for so a reconnect within the window can be correlated against its prior sent_offset. Default 60_000 (60 s); pass 0 to drop slots immediately on disconnect.

Source

pub fn with_replica_inboxes(self, receivers: Vec<ReplicaInboxReceiver>) -> Self

Install per-shard replica inboxes. The embedder pre- constructs nshards inbox pairs via crate::replica_inbox_pair, keeps the senders to hand to the per-shard replica runner threads, and passes the receivers here. The order of receivers is shard-major: index i ↔ shard i. Length must equal nshards. When this builder isn’t called, no shard has an inbox (standalone / primary-only behaviour).

Source

pub fn with_cluster(self, port_base: u16) -> Self

Enable single-node cluster mode: keys route by Redis-cluster slot (CRC16 {hashtag} & 16383, contiguous even ranges) and every shard i binds a second, deterministic listener at port_base + i that answers wrong-shard keys with -MOVED instead of forwarding. The SO_REUSEPORT listener on the main port keeps today’s full forward-anywhere behaviour for non-cluster clients.

Source

pub fn with_slowlog(self, slower_than_micros: i64, max_len: u32) -> Self

SLOWLOG tuning ([slowlog] config section). Default slower_than_micros = -1 (OFF) so the hot path never reads the clock — every enabled command otherwise pays an Instant::now() pair around dispatch, ~30 ns/op (≈9 % at 3 M ops/s). To match Redis’s 10 ms default, pass 10_000; 0 records all; -1 disables. max_len is the per-shard ring cap (default 128).

Source

pub fn with_advanced( self, spin_limit: u32, park_timeout_ms: u32, tick_check_every: u32, ring_capacity: usize, ) -> Self

Reactor tuning knobs ([advanced] config section). Defaults match the original hardcoded constants. ring_capacity is applied at SPSC ring construction (startup only); the other three are read at each iteration of the reactor loop, so values applied here take effect from the next shard.run() call.

Source

pub fn with_data_dir(self, dir: impl Into<PathBuf>) -> Self

Set the directory where shards snapshot to / load from. Default: ..

This sets the RUNTIME’s directory. It does not reach a Commands implementation’s own configuration, which is a separate object — so a server built this way answers CONFIG GET dir from that config rather than from here, and the two disagree unless the embedder sets both.

kevy::serve builds both from one Config, so the shipped binary never sees the gap; a programmatic build can, and a test that used CONFIG GET dir to identify its own server found . where it had passed a temp directory.

Source

pub fn with_accept_shards(self, n: Option<usize>) -> Self

Only shards 0..N arm accept SQE; rest stay compute-only. None = every shard accepts (the default; byte-identical to the pre-flag behaviour).

Source

pub fn with_max_clients(self, n: usize) -> Self

Total cap on active client connections. 0 = unlimited. Default 10_000. Per-shard slice is ceil(N / nshards).

Source

pub fn with_tier_budget(self, bytes: Option<u64>) -> Self

Transparent-tiering RAM budget for the whole process, in resolved bytes (the caller resolves auto / percent forms against kevy_sys::detected_memory_bound first). Split evenly across shards. None (default) = tiering off unless the minimal KEVY_TIER_BUDGET plain-bytes env knob is set.

Source

pub fn with_tier_spill_dir(self, dir: Option<PathBuf>) -> Self

Cold-tier spill dir override ([tiering] spill_dir). None (default) = <data_dir>/tier/.

Source

pub fn with_aof(self, on: bool) -> Self

Enable/disable the append-only log. Default: enabled.

Source

pub fn with_appendfsync(self, fsync: Fsync) -> Self

fsync policy for the AOF. Default EverySec matches Redis (lose at most ~1 s of writes on a crash). Always is zero-loss but ~50 % throughput; No defers everything to the OS pagecache.

Source

pub fn with_auto_aof_rewrite(self, pct: u32, min_size: u64) -> Self

Auto-trigger BGREWRITEAOF when the live AOF has grown by at least pct percent above its size at the previous rewrite, AND is at least min_size bytes. pct=0 disables auto-rewrite (clients can still run BGREWRITEAOF manually). Defaults: 100 % / 64 MiB.

Source

pub fn with_auto_rewrite_bytes(self, bytes: u64) -> Self

Absolute-size auto-rewrite trigger: compact whenever the AOF reaches bytes, regardless of growth ratio (0 = rule off). Complements Self::with_auto_aof_rewrite, whose growth rule lets a large log double before compacting.

Source

pub fn with_auto_rewrite_interval_secs(self, interval_secs: u64) -> Self

Time-based auto-rewrite trigger: compact at least every interval_secs seconds while the log grows (0 = rule off).

Source

pub fn with_replay_resync(self, resync: bool) -> Self

Best-effort boot replay: recover the good records behind a corrupt v2 AOF record instead of dropping them. Default false (strict).

Source§

impl<C: Commands> Runtime<C>

Source

pub fn run(self, stop: Arc<AtomicBool>) -> Result<()>

Spawn one thread per shard and run until stop is set.

Auto Trait Implementations§

§

impl<C> !Sync for Runtime<C>

§

impl<C> Freeze for Runtime<C>
where C: Freeze,

§

impl<C> RefUnwindSafe for Runtime<C>
where C: RefUnwindSafe,

§

impl<C> Send for Runtime<C>

§

impl<C> Unpin for Runtime<C>
where C: Unpin,

§

impl<C> UnsafeUnpin for Runtime<C>
where C: UnsafeUnpin,

§

impl<C> UnwindSafe for Runtime<C>
where C: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.