redis

Redis client for Kit using native Zig FFI

Files

FileDescription
.editorconfigEditor formatting configuration
.gitignoreGit ignore rules for build artifacts and dependencies
.tool-versionsasdf tool versions (Zig, Kit)
LICENSEMIT license file
README.mdThis file
examples/basic.kitBasic usage example
examples/live-smoke.kitRunnable live Redis smoke check
examples/redis.kitExample: redis
kit.tomlPackage manifest with metadata and dependencies
src/redis.kitRedis error type for typed error handling.
tests/redis.test.kitTests for redis
zig/kit_ffi.zigZig FFI module for kit ffi
zig/redis.zigZig FFI module for redis

Architecture

Command Flow

sequenceDiagram participant App participant Redis.kit participant Zig FFI participant Redis Server App->>Redis.kit: set / get / del Redis.kit->>Zig FFI: RESP Protocol Zig FFI->>Redis Server: TCP Command Redis Server->>Zig FFI: RESP Response Zig FFI->>Redis.kit: Parse Result Redis.kit->>App: Result

FFI Structure

graph TD A[Kit Code] -->|import Redis| B[src/redis.kit] B -->|extern-zig| C[zig/redis.zig] C --> D[zig/kit_ffi.zig] D --> E[TCP Socket] E --> F[Redis Server]

Dependencies

No Kit package dependencies.

Installation

kit add gitlab.com/kit-lang/packages/kit-redis.git

Usage

import Kit.Redis

Current API

kit-redis currently supports:

  • connection: connect, connect-timeout, connect-unix, connect-url, connect-url-timeout, close, ping, auth, auth-user, select-db
  • transactions: watch, unwatch, multi, exec, discard
  • strings: get, getdel, getex, getpex, getset, getrange, mget, set, mset, msetnx, setex, append, strlen, setrange, psetex, setnx, setnxex, setnxpx, del, unlink, del-many, unlink-many, rename, renamenx, exists?, exists-many, expire, expireat, pexpire, pexpireat, persist, touch, ttl, pttl
  • counters: incr, decr, incrby, incrbyfloat, decrby
  • lists: lpush, rpush, llen, lrange, lindex, lset, ltrim, lpos, lrem, rpoplpush, lpop, rpop
  • sorted sets: zadd, zincrby, zrem, zcard, zrank, zrevrank, zscore, zmscore, zcount, zlexcount, zunionstore, zunion, zinterstore, zinter, zdiff, zdiffstore, zremrangebyrank, zremrangebyscore, zremrangebylex, zrange, zrevrange, zrange-withscores, zrangebylex, zrevrangebylex, zrangebyscore, zrevrangebyscore, zpopmin, zpopmax, zrandmember, zscan
  • sets: sadd, srem, smove, smembers, sismember?, scard, sunionstore, sunion, sinterstore, sinter, sdiff, sdiffstore, spop, srandmember, sscan
  • hashes: hset, hsetnx, hset-many, hget, hmget, hincrby, hincrbyfloat, hdel, hdel-many, hexists?, hgetall, hkeys, hvals, hlen, hstrlen, hscan
  • utility: command, key-type, scan, dbsize, flushdb

See examples/basic.kit and examples/redis.kit for working examples that match the current exported API.

Generic Command Replies

command provides a generic Redis escape hatch for commands that do not have a dedicated typed wrapper yet:

match Redis.command conn ["PING"]
  | Ok (RedisSimpleString "PONG") -> println "pong"
  | Ok reply -> println "unexpected reply: ${show reply}"
  | Err err -> println "command failed: ${err}"

The returned RedisReply variants mirror RESP reply shapes:

  • RedisSimpleString String
  • RedisErrorString String
  • RedisInteger Int
  • RedisBulkString String
  • RedisNullBulkString
  • RedisArray [RedisReply]
  • RedisNullArray

Testing

Fast package checks:

kit test tests/redis.test.kit
zig test zig/redis.zig --cache-dir /tmp/kit-redis-cache --global-cache-dir /tmp/kit-redis-global-cache

Opt-in live Redis smoke check:

kit run examples/live-smoke.kit --allow=ffi,tcp

Optional environment variables for the live smoke script:

  • KIT_REDIS_HOST defaults to 127.0.0.1
  • KIT_REDIS_PORT defaults to 6379
  • KIT_REDIS_DB defaults to 9
  • KIT_REDIS_USERNAME enables ACL-style auth for the live smoke script
  • KIT_REDIS_PASSWORD enables an authenticated smoke flow against password-protected Redis

Notes

  • ttl returns Redis sentinel values unchanged: -1 means the key has no expiry and -2 means the key does not exist.
  • pttl returns the same sentinel values as ttl, but in milliseconds.
  • expireat and pexpireat accept absolute Unix timestamps, which is useful when higher-level code already has a concrete deadline instead of a relative TTL.
  • persist removes an existing expiry without rewriting the value, which is useful for promoting temporary keys to durable ones.
  • touch updates a key's access metadata without rewriting the value and returns whether the key existed.
  • key-type wraps Redis TYPE and returns the raw Redis type string, which is useful for debugging mixed key usage.
  • scan returns a record with cursor and keys, making it suitable for higher-level namespace invalidation loops.
  • dbsize reports the current key count in the selected database, which is useful for smoke tests and lightweight diagnostics.
  • del-many accepts a [String] and issues a single DEL command, which pairs naturally with scan for batched namespace invalidation.
  • unlink and unlink-many provide non-blocking invalidation paths that are often better fits for cache backends with larger values.
  • rename and renamenx support atomic key rotation, which is useful for publish/swap flows and versioned cache keys.
  • mget returns a list of Option String, preserving missing keys as None in the original key order.
  • exists-many returns the number of existing keys in a batch, which is useful for bulk cache presence checks without repeated exists? calls.
  • getdel atomically fetches and removes a key, which is useful for one-shot tokens or consume-once cache entries.
  • getex atomically fetches a key and resets its expiry in seconds, which is a better primitive for sliding TTL than separate get and expire calls.
  • getpex does the same as getex, but with millisecond precision for shorter-lived cache entries and leases.
  • getset atomically swaps a string value while returning the previous value, which is useful for draft/publish or compare-and-log style flows.
  • getrange and setrange expose Redis's substring and in-place overwrite primitives, which are useful when higher-level code wants partial string inspection or mutation without a full round trip.
  • mset accepts [{key: String, value: String}], which is a better fit for cache fill paths than alternating flat arguments.
  • msetnx applies the same record-based batch shape as mset, but fails cleanly when any destination key already exists.
  • append and strlen expose Redis's in-place string mutation and size inspection primitives without forcing a read-modify-write round trip in Kit code.
  • setnxex wraps SET key value EX seconds NX, which is the safer primitive for cache-lock or lease acquisition than separate setnx and expire calls.
  • incrbyfloat and decrby round out the basic counter surface for fractional and batched decrement flows.
  • psetex, pexpire, pttl, and setnxpx provide millisecond-precision expiry control for short-lived cache entries and leases.
  • lrange returns a list slice directly, which is a better fit for inspection and batch reads than repeated pop operations.
  • lpos, lrem, and rpoplpush round out the basic list surface for lookup, cleanup, and simple queue handoff flows.
  • zadd, zincrby, zrem, zcard, zrank, zrevrank, zscore, zcount, zrange, zrange-withscores, and zrangebyscore provide a usable first sorted-set slice for ranking, priority, and ordered window use cases.
  • set commands support lightweight grouping and membership checks, which is useful for tag-based invalidation and cache bookkeeping.
  • smove provides an atomic set-to-set transfer, which is useful for claim, migration, or workflow handoff flows.
  • spop returns an Option String and removes the selected member, which is useful for simple claim-one or consume-once set flows.
  • srandmember returns an Option String for lightweight sampling without removing the set member, which is useful for simple selection or sanity checks.
  • sscan returns {cursor, members} so larger sets can be traversed incrementally without materializing the full member list in one call.
  • hash commands are available for field-oriented state such as sessions, validators, or lightweight metadata records.
  • hset-many accepts [{field, value}] and returns the count of newly added fields, which fits batch metadata writes better than repeated hset calls.
  • hmget returns [Option String] in field order, which fits partial metadata reads without forcing a full hgetall.
  • hdel-many accepts [String] and deletes multiple hash fields in one command, which is useful for metadata cleanup without repeated hdel calls.
  • hgetall returns [{field, value}], which is useful when higher-level code needs a whole metadata record in one round trip.
  • hkeys and hvals expose the lighter-weight hash projection commands when you only need field names or values.
  • hlen returns the field count for a hash without fetching the full record.
  • hstrlen returns the size of a single hash field value without materializing the full value in Kit code.
  • hscan returns {cursor, items} so larger hashes can be traversed incrementally without pulling the full record into memory.
  • command is intended as an escape hatch; prefer the dedicated typed helpers where they exist.
  • connect-unix supports Redis deployments exposed through a Unix domain socket path.
  • connect-timeout and connect-url-timeout perform real timed TCP connects in milliseconds.
  • auth-user supports Redis ACL authentication for host/port and Unix-socket connections without requiring a URL.
  • examples/live-smoke.kit exercises connect, connect-url, cache-oriented commands, counters, and list operations against a real Redis server.
  • connect-url supports redis:// and rediss:// URLs with embedded credentials and /db paths, such as redis://:secret@localhost:6379/2, redis://kit-user:secret@localhost:6379/0, or rediss://cache.example.com:6380/0.
  • rediss:// uses Zig's TLS client with system CA verification. The default TLS port is 6380.

License

MIT License - see LICENSE for details.

Exported Functions & Types

RedisError

Redis error type for typed error handling. Variants distinguish between connection and command errors.

Variants

RedisConnectionError {message}
RedisCommandError {message}

RedisReply

Generic RESP reply type for the command escape hatch.

Variants

RedisSimpleString {String}
RedisErrorString {String}
RedisInteger {Int}
RedisBulkString {String}
RedisNullBulkString
RedisArray {_0}
RedisNullArray

connect

Connect to a Redis server at the specified host and port.

String -> Int -> Result Int RedisError

connect-timeout

Connect to a Redis server with a connection timeout in milliseconds.

String -> Int -> Int -> Result Int RedisError

connect-unix

Connect to a Redis server via Unix domain socket.

String -> Result Int RedisError

connect-url

Connect to a Redis server using a URL.

String -> Result Int RedisError

connect-url-timeout

Connect to a Redis server using a URL with a connection timeout in milliseconds.

String -> Int -> Result Int RedisError

close

Close a Redis connection and free associated resources.

Int -> Result Unit RedisError

ping

Send a PING command to test the connection.

Int -> Result String RedisError

auth

Authenticate with the Redis server using a password.

Int -> String -> Result Unit RedisError

auth-user

Authenticate with the Redis server using ACL username and password.

Int -> String -> String -> Result Unit RedisError

select-db

Select a Redis database by index.

Int -> Int -> Result Unit RedisError

watch

Watch one or more keys for changes before a later transaction.

Int -> [String] -> Result Unit RedisError

unwatch

Clear all watched keys on the current connection.

Int -> Result Unit RedisError

multi

Start a Redis transaction block on the current connection.

Int -> Result Unit RedisError

exec

Execute the queued commands in the current transaction.

Int -> Result RedisReply RedisError

discard

Discard the queued commands in the current transaction.

Int -> Result Unit RedisError

get

Get the value of a key.

Int -> String -> Result (Option String) RedisError

getdel

Get the value of a key and delete it atomically.

Int -> String -> Result (Option String) RedisError

getex

Get the value of a key and reset its expiration in seconds atomically.

Int -> String -> Int -> Result (Option String) RedisError

getpex

Get the value of a key and reset its expiration in milliseconds atomically.

Int -> String -> Int -> Result (Option String) RedisError

getset

Set the value of a key and return its previous value atomically.

Int -> String -> String -> Result (Option String) RedisError

getrange

Get a substring of a string value using inclusive start and stop offsets.

Int -> String -> Int -> Int -> Result String RedisError

mget

Get multiple values in a single Redis command.

Int -> [String] -> Result [(Option String)] RedisError

set

Set the value of a key.

Int -> String -> String -> Result Unit RedisError

mset

Set multiple key/value pairs in a single Redis command.

Int -> [RedisItem] -> Result Unit RedisError

msetnx

Set multiple key/value pairs only if none of the keys already exist.

Int -> [RedisItem] -> Result Bool RedisError

setex

Set the value of a key with expiration in seconds.

Int -> String -> Int -> String -> Result Unit RedisError

append

Append text to the existing string value at a key.

Int -> String -> String -> Result Int RedisError

strlen

Get the length of a string value in bytes.

Int -> String -> Result Int RedisError

setrange

Overwrite part of a string value starting at the given byte offset.

Int -> String -> Int -> String -> Result Int RedisError

psetex

Set the value of a key with expiration in milliseconds.

Int -> String -> Int -> String -> Result Unit RedisError

setnx

Set the value of a key only if it does not already exist.

Int -> String -> String -> Result Bool RedisError

setnxex

Atomically set the value of a key with expiration in seconds only if it does not already exist.

Int -> String -> Int -> String -> Result Bool RedisError

setnxpx

Atomically set the value of a key with expiration in milliseconds only if it does not already exist.

Int -> String -> Int -> String -> Result Bool RedisError

del

Delete a key.

Int -> String -> Result Int RedisError

Asynchronously delete a key.

Int -> String -> Result Int RedisError

del-many

Delete multiple keys in a single Redis command.

Int -> [String] -> Result Int RedisError

Asynchronously delete multiple keys in a single Redis command.

Int -> [String] -> Result Int RedisError

rename

Rename a key atomically, overwriting the destination if it exists.

Int -> String -> String -> Result Unit RedisError

renamenx

Rename a key only if the destination does not already exist.

Int -> String -> String -> Result Bool RedisError

exists?

Check if a key exists.

Int -> String -> Result Bool RedisError

exists-many

Count how many of the given keys currently exist.

Int -> [String] -> Result Int RedisError

key-type

Get the Redis type of a key.

Int -> String -> Result String RedisError

expire

Set an expiration on a key in seconds.

Int -> String -> Int -> Result Bool RedisError

expireat

Set an absolute expiration timestamp on a key in seconds since the Unix epoch.

Int -> String -> Int -> Result Bool RedisError

pexpire

Set an expiration on a key in milliseconds.

Int -> String -> Int -> Result Bool RedisError

pexpireat

Set an absolute expiration timestamp on a key in milliseconds since the Unix epoch.

Int -> String -> Int -> Result Bool RedisError

persist

Remove the expiration from a key.

Int -> String -> Result Bool RedisError

touch

Update the last access time of a key without rewriting its value.

Int -> String -> Result Bool RedisError

ttl

Get the remaining time to live of a key.

Int -> String -> Result Int RedisError

pttl

Get the remaining time to live of a key in milliseconds.

Int -> String -> Result Int RedisError

incr

Increment the integer value of a key by 1.

Int -> String -> Result Int RedisError

decr

Decrement the integer value of a key by 1.

Int -> String -> Result Int RedisError

incrby

Increment the integer value of a key by the provided amount.

Int -> String -> Int -> Result Int RedisError

incrbyfloat

Increment the floating-point value of a key by the provided amount.

Int -> String -> Float -> Result Float RedisError

decrby

Decrement the integer value of a key by the provided amount.

Int -> String -> Int -> Result Int RedisError

lpush

Push a value to the head (left) of a list.

Int -> String -> String -> Result Int RedisError

rpush

Push a value to the tail (right) of a list.

Int -> String -> String -> Result Int RedisError

llen

Get the length of a list.

Int -> String -> Result Int RedisError

lrange

Get a range of values from a list.

Int -> String -> Int -> Int -> Result [String] RedisError

lindex

Get a single value from a list by index.

Int -> String -> Int -> Result (Option String) RedisError

lset

Replace a list value at an index.

Int -> String -> Int -> String -> Result Unit RedisError

ltrim

Trim a list to the inclusive index range.

Int -> String -> Int -> Int -> Result Unit RedisError

lpos

Find the first index of a list value.

Int -> String -> String -> Result (Option Int) RedisError

lrem

Remove list elements equal to the given value.

Int -> String -> Int -> String -> Result Int RedisError

rpoplpush

Pop a value from the tail of one list and push it onto the head of another list atomically.

Int -> String -> String -> Result (Option String) RedisError

lpop

Pop a value from the head (left) of a list.

Int -> String -> Result (Option String) RedisError

rpop

Pop a value from the tail (right) of a list.

Int -> String -> Result (Option String) RedisError

zadd

Add a member to a sorted set with the given score.

Int -> String -> Float -> String -> Result Bool RedisError

zincrby

Increment the score of a sorted set member.

Int -> String -> Float -> String -> Result Float RedisError

zrem

Remove a member from a sorted set.

Int -> String -> String -> Result Bool RedisError

zcard

Get the number of members in a sorted set.

Int -> String -> Result Int RedisError

zrank

Get the zero-based rank of a sorted set member in ascending score order.

Int -> String -> String -> Result (Option Int) RedisError

zrevrank

Get the zero-based rank of a sorted set member in descending score order.

Int -> String -> String -> Result (Option Int) RedisError

zscore

Get the score of a sorted set member.

Int -> String -> String -> Result (Option Float) RedisError

zmscore

Get the scores of multiple sorted set members in one Redis command.

Int -> String -> [String] -> Result [(Option Float)] RedisError

zcount

Count how many sorted set members have scores within the inclusive score range.

Int -> String -> Float -> Float -> Result Int RedisError

zlexcount

Count how many sorted set members fall within the inclusive lexicographical range.

Int -> String -> String -> String -> Result Int RedisError

zunionstore

Store the union of multiple sorted sets in a destination sorted set.

Int -> String -> [String] -> Result Int RedisError

zunion

Return the union of multiple sorted sets as member names.

Int -> [String] -> Result [String] RedisError

zinterstore

Store the intersection of multiple sorted sets in a destination sorted set.

Int -> String -> [String] -> Result Int RedisError

zinter

Return the intersection of multiple sorted sets as member names.

Int -> [String] -> Result [String] RedisError

zdiff

Return the difference of multiple sorted sets as member names.

Int -> [String] -> Result [String] RedisError

zdiffstore

Store the difference of multiple sorted sets in a destination sorted set.

Int -> String -> [String] -> Result Int RedisError

zremrangebyrank

Remove sorted set members whose ranks fall within the inclusive rank range.

Int -> String -> Int -> Int -> Result Int RedisError

zremrangebyscore

Remove sorted set members whose scores fall within the inclusive score range.

Int -> String -> Float -> Float -> Result Int RedisError

zremrangebylex

Remove sorted set members whose values fall within the inclusive lexicographical range.

Int -> String -> String -> String -> Result Int RedisError

zrange

Get a range of members from a sorted set by index.

Int -> String -> Int -> Int -> Result [String] RedisError

zrevrange

Get a range of members from a sorted set by index in descending score order.

Int -> String -> Int -> Int -> Result [String] RedisError

zrange-withscores

Get a range of sorted set members with their scores by index.

Int -> String -> Int -> Int -> Result [RedisSortedSetItem] RedisError

zrangebylex

Get sorted set members whose values fall within the inclusive lexicographical range.

Int -> String -> String -> String -> Result [String] RedisError

zrevrangebylex

Get sorted set members whose values fall within the inclusive lexicographical range in descending order.

Int -> String -> String -> String -> Result [String] RedisError

zrangebyscore

Get sorted set members whose scores fall within the inclusive score range.

Int -> String -> Float -> Float -> Result [String] RedisError

zrevrangebyscore

Get sorted set members whose scores fall within the inclusive score range in descending order.

Int -> String -> Float -> Float -> Result [String] RedisError

zpopmin

Pop and return the member with the lowest score from a sorted set.

Int -> String -> Result (Option RedisSortedSetItem) RedisError

zpopmax

Pop and return the member with the highest score from a sorted set.

Int -> String -> Result (Option RedisSortedSetItem) RedisError

zrandmember

Return a random member from a sorted set without removing it.

Int -> String -> Result (Option String) RedisError

zscan

Incrementally scan a sorted set.

Int -> String -> Int -> String -> Int -> Result {cursor: Int, items: [RedisSortedSetItem]} RedisError

sadd

Add a member to a set.

Int -> String -> String -> Result Bool RedisError

srem

Remove a member from a set.

Int -> String -> String -> Result Bool RedisError

smove

Move a member atomically from one set to another.

Int -> String -> String -> String -> Result Bool RedisError

smembers

Get all members from a set.

Int -> String -> Result [String] RedisError

sismember?

Check if a set contains a member.

Int -> String -> String -> Result Bool RedisError

scard

Get the number of members in a set.

Int -> String -> Result Int RedisError

sunionstore

Store the union of multiple sets in a destination set.

Int -> String -> [String] -> Result Int RedisError

sunion

Return the union of multiple sets as member names.

Int -> [String] -> Result [String] RedisError

sinterstore

Store the intersection of multiple sets in a destination set.

Int -> String -> [String] -> Result Int RedisError

sinter

Return the intersection of multiple sets as member names.

Int -> [String] -> Result [String] RedisError

sdiff

Return the difference of multiple sets as member names.

Int -> [String] -> Result [String] RedisError

sdiffstore

Store the difference of multiple sets in a destination set.

Int -> String -> [String] -> Result Int RedisError

spop

Pop and return a random member from a set.

Int -> String -> Result (Option String) RedisError

srandmember

Return a random member from a set without removing it.

Int -> String -> Result (Option String) RedisError

sscan

Incrementally scan set members using a cursor, pattern, and count hint.

Int -> String -> Int -> String -> Int -> Result {cursor: Int, members: [String]} RedisError

hset

Set a field in a hash.

Int -> String -> String -> String -> Result Bool RedisError

hsetnx

Set a field in a hash only if it does not already exist.

Int -> String -> String -> String -> Result Bool RedisError

hget

Get the value of a hash field.

Int -> String -> String -> Result (Option String) RedisError

hincrby

Increment an integer hash field by the provided amount.

Int -> String -> String -> Int -> Result Int RedisError

hincrbyfloat

Increment a floating-point hash field by the provided amount.

Int -> String -> String -> Float -> Result Float RedisError

hset-many

Set multiple hash fields in a single Redis command.

Int -> String -> [RedisHashItem] -> Result Int RedisError

hmget

Get the values of multiple hash fields.

Int -> String -> [String] -> Result [(Option String)] RedisError

hdel

Delete a field from a hash.

Int -> String -> String -> Result Int RedisError

hdel-many

Delete multiple fields from a hash in a single Redis command.

Int -> String -> [String] -> Result Int RedisError

hexists?

Check if a hash field exists.

Int -> String -> String -> Result Bool RedisError

hgetall

Get all fields and values from a hash.

Int -> String -> Result [RedisHashItem] RedisError

hkeys

Get all field names from a hash.

Int -> String -> Result [String] RedisError

hvals

Get all values from a hash.

Int -> String -> Result [String] RedisError

hlen

Get the number of fields in a hash.

Int -> String -> Result Int RedisError

hstrlen

Get the string length of a hash field value.

Int -> String -> String -> Result Int RedisError

hscan

Incrementally scan hash fields and values using a cursor, pattern, and count hint.

Int -> String -> Int -> String -> Int -> Result {cursor: Int, items: [RedisHashItem]} RedisError

command

Execute an arbitrary Redis command expressed as command parts.

Int -> [String] -> Result RedisReply RedisError

scan

Incrementally scan keys using a cursor, pattern, and count hint.

Int -> Int -> String -> Int -> Result {cursor: Int, keys: [String]} RedisError

dbsize

Get the number of keys in the selected database.

Int -> Result Int RedisError

flushdb

Remove all keys from the selected database.

Int -> Result Unit RedisError