jonnifyechomq

Trafikist · module 05

TRA and native values

The module’s second family: two metadata commands, four bitmap commands on ordinary strings, a versioned C table for other modules and three bundled Lua sources. A bitmap lives in a string; no native value type is registered.

trafikey registers two families from one table. EMQ.* carries the job core and the bus's three writes and runs the command grammar; TRA.* is the other six rows, and it runs a grammar of its own: no numkeys, no fence, no brand read. Two TRA commands report the module’s metadata, and four read and write the bits of one ordinary string key, the high bit of byte 0 first. Of the six, TRA.SETBIT is the only one that writes a key, and it replicates the command itself, where every EMQ write replicates as its effects. Beside the commands the module exports a versioned C table that hands other modules the bundled Lua sources, and installing those sources stays an explicit act. A native bitmap value type does not exist: the default build registers no module data type, and the one data type in the source is a persistence probe behind a feature that is off by default. Pick a command to read its arguments, its reply and what it writes.

The second family

The six TRA rows follow the EMQ rows in registry::TABLE and register the same way: one row, one command, with its flags, its key-spec and its ACL categories. The registration table reads the rows. What runs inside differs. A TRA handler takes no numkeys, reads no {emq}:version, runs no fence and calls no begin_writes: the server checks the arity, the handler parses its arguments, and a bitmap command opens its one key. The two metadata commands open no key at all.

The six TRA commands · pick one

registry::TABLE · six TRA rows keyless metadata one ordinary string key TRA.CAPABILITIES TRA.INFO TRA.SETBIT TRA.GETBIT TRA.STRLEN TRA.BITCOUNT TRA.SETBIT · the one write · replicated verbatim
TRA.SETBIT key offset 0|1 · arity 4 · write deny-oom · ACL write bitmap slow
key: reads one ordinary string; a missing key reads as empty
writes: writes that string in place, grown with zero bytes when the bit lies past the end; an unchanged bit inside the string writes nothing
reply: the previous bit, 0 or 1
refusals: ERR TRA invalid-offset · ERR TRA invalid-argument · ERR TRA limit · WRONGTYPE
replicated: the command itself, verbatim, with a setbit keyspace event, whenever it writes
grammar: no numkeys, no fence, no brand read

Six commands, one string key at most, and no fence: TRA shares the module’s table and loader, not its grammar.

Two metadata commands

TRA.CAPABILITIES and TRA.INFO take no argument and read no key. Each answers a map built in insertion order: a RESP3 map, or on a RESP2 connection the same pairs as one flat array. TRA.CAPABILITIES reports eight pairs: the module’s name, the TRA metadata version string, a stage, the shared API version, the bitmap command count, and three facts about the shared API and the bundled Lua. The bitmap count is not a constant. It is counted from the registered TRA rows that carry the bitmap token, so a build without one of the four rows reports three. TRA.INFO, flagged admin, reports the name, the same version string and two call counters.

// trafikey — tra::capabilities and tra::info, the two metadata commands, with the counter they bump
fn increment(value: &AtomicU64) {
    // Counters saturate rather than wrapping to an apparently fresh observation.
    let _ = value.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| {
        Some(old.saturating_add(1))
    });
}
// …
pub(crate) fn capabilities(ctx: &Context, _: Vec<ValkeyString>) -> ValkeyResult {
    increment(&CAPS_CALLS);
    // Derived from the registration table: only registered bitmap rows are counted.
    let bitmap_commands =
        registry::capabilities(Family::Tra, |name| registry::registered(ctx, name))
            .filter(|token| *token == "bitmap")
            .count() as i64;
    reply_pairs(
        ctx,
        &[
            (b"module", Field::Text(b"trafikey")),
            (b"version", Field::Text(b"0.1.0-tra1")),
            (b"stage", Field::Text(b"abi-lua-preview")),
            (b"api_version", Field::Int(1)),
            (b"bitmap_commands", Field::Int(bitmap_commands)),
            (b"shared_api", Field::Int(1)),
            (b"bundled_lua", Field::Int(1)),
            (b"lua_scripts", Field::Int(3)),
        ],
    )
}
pub(crate) fn info(ctx: &Context, _: Vec<ValkeyString>) -> ValkeyResult {
    increment(&INFO_CALLS);
    reply_pairs(
        ctx,
        &[
            (b"module", Field::Text(b"trafikey")),
            (b"version", Field::Text(b"0.1.0-tra1")),
            (
                b"capabilities_calls",
                Field::Int(bounded_count(&CAPS_CALLS)),
            ),
            (b"info_calls", Field::Int(bounded_count(&INFO_CALLS))),
        ],
    )
}

The counters are two atomics in process memory: they start at zero in each server process and stop at the top of their range instead of wrapping to a value that would read as fresh. The version string these two commands report belongs to TRA alone; it is neither the version in the module declaration nor the crate version EMQ.VERSION reports. On the stand’s module node TRA.CAPABILITIES answers those eight pairs in the order above, and TRA.CAPABILITIES x gets the server’s own ERR wrong number of arguments reply.

The metadata commands describe the module without touching the keyspace, and even the bitmap count is read from the table.

One write, replicated verbatim

TRA.SETBIT is the only TRA command that writes a key. When it changes a bit, or grows the string to reach one, it writes the string’s bytes in place, raises a setbit keyspace event in the string class, and has the server replicate the command verbatim: the AOF and the replicas receive TRA.SETBIT with the arguments the client sent. A call that leaves a bit inside the string as it was writes nothing and replicates nothing.

// trafikey — tra::bitmap::setbit, its two exits
    // Equal bit without growth is not a logical mutation: no write, no replication, no WATCH touch.
    if !grows && previous == bit {
        return Ok(ValkeyValue::Integer(i64::from(previous)));
    }
    // … the string reopened for writing, grown when needed, the bit set or cleared
    raw::close_key(key);
    ctx.notify_keyspace_event(NotifyEvent::STRING, "setbit", name);
    ctx.replicate_verbatim();
    Ok(ValkeyValue::Integer(i64::from(previous)))

Every EMQ write goes the other way. An EMQ handler calls the server itself with the ! flag, so each write it makes, an HSET, a ZADD, a ZREM, reaches the AOF and the replicas as that write, and the writes of one command arrive inside one MULTI/EXEC. An EMQ handler never replicates its own command. One guard, then effects reads that path.

The AOF of a TRA.SETBIT holds TRA.SETBIT; the AOF of an EMQ write holds the writes it made.

A C table and three sources

The library carries three Lua files compiled into it: a capabilities wrapper, a bounded bitmap count over an ordinary string, and a Function library that holds both. The last step of init exports one C getter, trafikey_get_api_v1, under that name. Another module in the same server requests it by name, negotiates a version and a size, and receives a read-only table whose functions hand back the source bytes by id. Nothing in the module loads a script or a library into the server: an authorized caller does that with SCRIPT LOAD or FUNCTION LOAD. The second dive reads the table and the three sources.

The module ships its Lua as bytes; putting a script into the server is someone else’s authorized step.

No native value type

Every TRA bitmap is an ordinary string the server owns. The module declaration registers no data type and lists no commands of its own; every command arrives through the table. The only module data type in the source, traprobe1, compiles under the probe-type feature, which the crate does not turn on by default. It exists to prove that a module type with RDB save and load and AOF rewrite survives a restart, and it is never part of a shipped artifact.

// trafikey — the module declaration: no data types, no commands of its own
valkey_module! {
    name: "trafikey",
    version: 100,
    allocator: (ValkeyAlloc, ValkeyAlloc),
    data_types: [],
    preload: preload,
    init: init,
    commands: [],
}

Today a TRA bitmap is a string the server stores and saves like any other; the module owns the commands, not the value.

The dives

Three dives read the family in the real trafikey sources: the bitmap commands, the C table with the Lua it hands out, and the value type that is not there.

built page ready to read

Pattern & implementation

Where Redis Patterns Applied teaches a bitmap as one string with a flag per bit, this module reads the module commands that work on exactly such a string.

the pattern (Redis Patterns Applied)

A bitmap is one string whose bit N is the flag for entity N, set and read in place and counted without enumerating the entities. Bitmaps teaches it.

the implementation (trafikey)

Four TRA commands over that ordinary string, high bit first, with their own parsers and refusals and the one write replicated verbatim; two metadata commands; a C table and three Lua sources beside them; and no native value type.

Take the dives in order. After the third, the part closes with the workshop, which runs one transition on both executors.

References

Sources

Related in this course