Trafikist · module 01
Valkey and the module
Native code the server loads at startup, and a module that checks its host, its APIs and its own table before it serves one command.
Trafikist is Valkey plus one Rust module. This module reads that module the way the server
meets it: a shared library named on a loadmodule line, loaded when the server starts,
registering commands through the module API. The module is trafikey.
Before it registers anything it refuses the load unless the host is a Valkey 9 server, every host API it calls
is present and the loadmodule line passes no arguments. Then every command registers
from one table, and init refuses the load unless that table and the registered set
agree. The Protocol's native module introduced the second
executor; this module goes underneath it.
Native code, loaded at startup
A Valkey module is a shared library of native code. The server loads it when it starts, from a
loadmodule line in its configuration, calls the module's load entry point, and from
then on runs the module's commands when clients call them. trafikey is a Rust crate
built as exactly that kind of library: a cdylib, a shared object with a C ABI and no
network listener of its own.
# trafikey — the crate manifest: a library the server loads, with no server of its own [package] name = "trafikey" # … [lib] crate-type = ["cdylib"] # … # The cdylib is loaded by Valkey; no standalone RESP listener or bitmap data type is implemented here.
The line that loads it is one directive, loadmodule,
naming the shared library at /opt/trafikey/libtrafikey.so. The deploy folder keeps
that line as a fragment of its own, module.load.conf, under a warning: the fragment is
never a complete server configuration, it is included only from the observed startup path after a first
rehearsal, and loading trusted native code is itself a production change.
The fragment is a reviewed recipe, and the deploy folder records its runtime as
unverified. Where the module runs is the stand: a node of its own on port 6391, whose configuration carries
the loadmodule line, beside the Echo service node on port 6390, which loads no
module. The installer builds the module on the machine that runs it, as
libtrafikey.dylib on macOS and libtrafikey.so on Linux; the
release’s own artifact is a darwin-arm64 .dylib.
A module is a library the server loads, not a service beside it: one line at startup, on a node that agrees to run native code.
What trafikey checks before it registers anything
Loading runs in three steps inside that one entry point. First the gate, preload,
before any command exists: the host's major version must be 9, every host API the module calls must be
present, and the loadmodule line must pass no arguments. Then every row of the
registration table registers its command. Then init runs: it sets each row's ACL
categories and refuses the load unless the table and the registered set are equal, reads the server's
process identity, records whether the server runs in cluster mode, and exports the module's shared C API.
preload and init each answer
Status::Ok or Status::Err, and an
Err refuses the load.
// trafikey — preload, the load gate the module declaration names /// Load gate, before anything registers: no module arguments, a Valkey 9.x host, and every /// host API this module calls present. raw wrappers unwrap the host pointers and the release /// profile aborts on panic, so a missing API must refuse the load instead of killing the node. fn preload(ctx: &Context, args: &[ValkeyString]) -> Status { let apis = registry::host_apis_present(); match ctx.get_server_version() { // all three at once: every API present, no arguments, major 9 Ok(v) if apis && args.is_empty() && v.major == 9 => Status::Ok, // anything else, a version the host cannot report included, refuses the load _ => Status::Err, } }
The load path · pick a host
preload: Status::Ok (every host API present, no arguments, major 9)
register: 24 commands from the table (18 EMQ.*, 6 TRA.*)
init: ACL categories set on every row · run_id read and held · mode recorded: standalone · shared API exported
serving: every EMQ.* command passes the mode check; EMQ.VERSION lists 17 capability tokens
The gate runs before the first command exists, so on a host the module cannot run on, no
EMQ.* or TRA.* command is ever registered.
One table, two families
Every command arrives through one table. The module's declaration lists no commands of its own; each row
of registry::TABLE carries a command's name, family, arity, flags, key-spec, ACL
categories and capability tokens, and four things derive from it: registration, the ACL categories
init sets, the capability list EMQ.VERSION advertises, and
the bitmap count TRA.CAPABILITIES reports. The default build registers twenty-four
commands: eighteen EMQ.* rows (the read-only EMQ.VERSION,
thirteen job-core write verbs, three bus write verbs and the administrative
EMQ.INSTALL) and six
TRA.* rows (two metadata commands and four bitmap commands on ordinary
strings).
// trafikey — the crate's own rule, from its module documentation //! A command exists by having its row in [`registry::TABLE`]; its handler stays in its family's //! module. `init` sets every row's ACL categories and refuses the load on any mismatch.
A command exists by having its row: the table is the module's whole command surface.
Standalone only
The module serves standalone servers. init reads the server mode once. On a
cluster-enabled server the module still loads and every command stays registered, but every
EMQ.* write verb refuses with EMQWIRE expected a standalone server
but cluster mode is enabled before it reads a key, and EMQ.VERSION advertises
no capability. The TRA.* commands carry no such check. A refused call writes
nothing: the mode check is the first thing the fence does, and the fence comes before every read.
Loaded is not served: on a cluster the commands exist, answer, and refuse every write.
The dives
Three dives read the module as the server meets it, each grounded in the real
trafikey sources: the load, the table, and the one server mode it serves.
Loading the module
The preload gate: Valkey 9, every host API, no arguments. Then init in its order: ACL categories, the server epoch, the server mode, the shared API.
The registration table
One row yields the command, its flags, its key-spec, its ACL categories and its capability tokens; three real rows, and the derivations that read them.
Standalone only
On a cluster every EMQ command stays registered but refuses its writes, and EMQ.VERSION advertises nothing, so a client refuses the node.
Pattern & implementation
Where Redis Patterns Applied teaches a pattern pushed below the language line becoming a protocol, this module reads the place the job core goes one step further down: native code inside the server process.
An agreement every runtime keeps — the keys, the fields, the atomic steps — stops being a library and becomes a protocol once it lives below the language line. Patterns become protocol teaches it.
A Rust cdylib the server loads at startup with loadmodule;
a gate that refuses a non-9 host, a missing host API or any argument; twenty-four commands from one table;
an init that refuses the load on a table mismatch; standalone servers only.
Take the dives in order. The next module of the part, The command grammar, reads the order every job-core and bus write verb runs once it is registered.
References
Sources
- Valkey — Modules introduction — what a module is: native code the server loads, which registers commands.
- Valkey — MODULE LOAD — the runtime form of the
loadmoduledirective; trafikey is loaded at startup. - Valkey — Modules API reference — the host API the gate checks: command registration, key-specs, ACL categories, shared APIs.
- Valkey — INFO — the
serversection whoserun_idinit reads once. - Valkey — Cluster specification — the server mode the module refuses to serve.
Related in this course
- The native module — the Protocol's bridge into this part: the second executor.
- Commands, not scripts — the command form and EVAL's key-spec.
- The native fence — the read every write verb starts with.
- The Protocol — the keyspace, the record and the Lua layer the module mirrors.
- redis-patterns · Patterns become protocol — the near side of the door.