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}

Entry type for batch string writes.

Entry type for batch hash writes and full hash reads.

Entry type for sorted set reads with scores.

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