Skip to main content

Crate kevy_rt

Crate kevy_rt 

Source
Expand description

kevy-rt — shared-nothing, thread-per-core runtime.

Each core runs its own reactor (kqueue/epoll) and owns one shard of the keyspace (hash(key) % nshards). There is no shared mutable state and no lock on the hot path — cores communicate only by message passing over channels, woken via a self-pipe (kevy_sys::Waker). Connections are spread across cores by SO_REUSEPORT; a command whose key lives on another core is forwarded to that core, executed there, and the reply routed back to the originating connection.

Per-connection reply ordering is preserved (RESP is pipelined): each command gets a monotonic seq; replies are emitted only in contiguous seq order, so an async cross-core reply never overtakes an earlier one.

The cross-core channel currently uses std::sync::mpsc (pure Rust, zero deps); swapping in a lock-free SPSC/MPSC ring is a perf-polish item. Command semantics are injected via the Commands trait, keeping the runtime independent of the concrete command set. Part of the kevy server.

§Module map

  • Runtime (in runtime) — public entry point; spawns one shard per core.
  • shard — the per-core reactor: sockets, the inbound queue, reply flushing.
  • exec — command semantics: routing, execution, and result reduction.
  • message — internal cross-core work/result types.
  • conn — per-connection state (input/output, seq ring, subscriptions).
  • reduce — reply reduction (materialize) and pure helpers (set algebra, shard hashing, pub/sub framing).

§Example

Implement Commands for your command set and run it. (Store is re-exported so you don’t need a separate dependency.)

use kevy_rt::{ArgvView, Commands, Route, Runtime, Store, TxnKind};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

#[derive(Clone)]
struct MyCommands;
impl Commands for MyCommands {
    fn route<A: ArgvView + ?Sized>(&self, args: &A) -> Route {
        if args.len() >= 2 { Route::Single(1) } else { Route::Local }
    }
    fn dispatch<A: ArgvView + ?Sized>(&self, _store: &mut Store, _args: &A) -> Vec<u8> {
        b"+OK\r\n".to_vec()
    }
    fn is_quit<A: ArgvView + ?Sized>(&self, args: &A) -> bool {
        args.first().is_some_and(|c| c.eq_ignore_ascii_case(b"QUIT"))
    }
    fn is_write<A: ArgvView + ?Sized>(&self, _args: &A) -> bool { false }
    fn txn_kind<A: ArgvView + ?Sized>(&self, _args: &A) -> TxnKind { TxnKind::Other }
}

// One shard per core, listening on 127.0.0.1:6379, until `stop` is set.
let rt = Runtime::new([127, 0, 0, 1], 6379, 4, MyCommands);
rt.run(Arc::new(AtomicBool::new(false))).unwrap();

Structs§

Argv
A parsed command’s argument vector.
ArgvBorrowed
A parsed command’s argument vector that borrows its bytes from a contiguous input buffer.
LiveRuntimeConfig
Live snapshot of the runtime-owned knobs that may have been changed since this shard’s last tick. Built by the Commands impl from its own config source (e.g. kevy reads config_global). Each Some(_) is applied to the shard; each None leaves the existing setting alone.
NotificationFlags
Parsed view of NotificationSection::notify_keyspace_events. The runtime caches this struct per-shard (hot-reload via the existing LiveRuntimeConfig tick path) so the per-write-command check reduces to four bool reads on the hot path.
ReplicaInboxReceiver
Receiver end. Lives inside the (private) Shard; drained once per reactor tick. Constructed by replica_inbox_pair and handed to the runtime via Runtime::with_replica_inboxes.
ReplicaInboxSender
Sender end of a per-shard replica inbox. Send + Clone + Sync (one std::sync::mpsc::Sender, no extra state) so the embedder can hand it freely to runner threads.
ReplicatedApplyGuard
RAII guard that marks the current thread as “applying a replicated frame” for the guard’s lifetime. The replica runner (T1.29(b)) enters this scope before each dispatch call so the apply doesn’t re-push the frame into this shard’s own backlog.
ResolvedCmd
Per-command verb-resolution result. Produced once by Commands::resolve in the reactor’s parse-then-dispatch loop, reused for routing decisions, AOF logging, and the QUIT branch — so the per-cmd upper_verb cost goes from 4× down to 1×.
Runtime
The public entry point: configure and run the thread-per-core server.
Store
A single-database keyspace.
XGroupCtx
The GROUP <name> <consumer> (+ NOACK) context an XREADGROUP gather carries to each per-stream sub-query.

Enums§

BlockHint
How a command wants to block, if at all. Returned by Commands::resolve inside crate::ResolvedCmd so the verb-table lookup happens once per command. None is the zero-cost default for every non-blocking verb (≥ 99.9 % of dispatches in steady state).
BlockKind
Which blocking command a waiter is parked in. Drives both timeout-nil shape and wake-retry dispatch.
Fsync
When to fsync the AOF to disk.
NotifyClass
Keyspace-notification event class — what category a write command belongs to, so the runtime can match it against the per-conn notify_keyspace_events flags before publishing.
ReplicaApply
One event delivered from a replica runner to its target shard. Mirrors kevy_replicate::replica::ReplicaEvent except Frame carries an owned Argv (already decoded by the runner) instead of a DecodedFrame { offset, argv } — the offset is gap-checked by the runner on the way in, so the shard doesn’t need it.
RespVersion
Which version of RESP a connection is speaking. Negotiated via the HELLO command — RESP2 is the default for backwards compatibility with every Redis 6.x and earlier client; RESP3 is opt-in via HELLO 3 and unlocks the additive reply types (Reply::Map / Reply::Set / Reply::Double / Reply::Boolean / Reply::Verbatim / Reply::BigNumber / Reply::Null / Reply::Push / Reply::BlobError) plus out-of-band push frames for PUBLISH delivery.
Route
How a command maps onto shards.
SlowlogSub
Parsed SLOWLOG <sub> [args] decision — picked at routing time so the runtime knows whether to fan out or short-circuit.
TxnKind
Transaction-control classification for a command.

Traits§

ArgvView
Read-only view over a parsed command’s argument vector.
Commands
Command-set semantics injected into the runtime. Cloned to every core, so it must be cheap/stateless to clone.

Functions§

parse_slowlog_sub
Parse args ( [verb, sub, ...] ) into a SlowlogSub. Verb name is assumed to already be SLOWLOG (the caller’s route table dispatched to here). Embedders call this from their Commands::resolve / Commands::route impl.
replica_inbox_pair
Create a matched (sender, receiver) pair for one shard’s replica inbox. The embedder calls this nshards times before Runtime::run.
shard_slot_range
The contiguous slot range [start, end] (inclusive, CLUSTER SLOTS shape) shard i of n owns: [ceil(i·16384/n), ceil((i+1)·16384/n) - 1]. Exact inverse of reduce::slot_to_shard’s multiply-shift.