redis#
redis client for zig implementing RESP (REdis Serialization Protocol).
usage#
const redis = @import("redis");
var client = try redis.Client.connect(allocator, "localhost", 6379);
defer client.close();
// strings
var str = client.strings();
try str.set("key", "value");
if (try str.get("key")) |val| { ... }
// hashes
var hash = client.hashes();
_ = try hash.hset("user:1", &.{
.{ "name", "alice" },
.{ "email", "alice@example.com" },
});
const all = try hash.hgetAll("user:1");
// lists
var list = client.lists();
_ = try list.rpush("queue", &.{ "a", "b", "c" });
if (try list.lpop("queue")) |item| { ... }
// sets
var set = client.sets();
_ = try set.sadd("tags", &.{ "redis", "fast" });
const common = try set.sinter(&.{ "set1", "set2" });
// sorted sets
var zset = client.sortedSets();
_ = try zset.zadd("scores", &.{
.{ .score = 100, .member = "alice" },
.{ .score = 85, .member = "bob" },
}, .{});
const top = try zset.zrangeWithScores("scores", 0, 2, .{ .rev = true });
// streams
var stream = client.streams();
const id = try stream.xadd("events", .auto, &.{.{ "type", "login" }});
try stream.xgroupCreate("events", "workers", "0", true);
const entries = try stream.xreadgroup("workers", "worker-1", &.{"events"}, &.{">"}, .{});
data types#
strings#
get, set, setNx, setEx, incr, incrBy, decr, decrBy, mget, mset, append, strlen
hashes#
hset, hget, hmget, hdel, hexists, hlen, hincrBy, hgetAll, hkeys, hvals, hscan
lists#
lpush, rpush, lpop, rpop, llen, lrange, lindex, lset, lrem, ltrim, blpop, brpop, lmove, blmove
sets#
sadd, srem, sismember, smismember, smembers, scard, spop, srandmember, sunion, sunionstore, sinter, sinterstore, sintercard, sdiff, sdiffstore, smove, sscan
sorted sets#
zadd, zrem, zscore, zrank, zrevrank, zcard, zcount, zincrBy, zrange, zrangeWithScores, zpopmin, zpopmax, bzpopmin, bzpopmax, zscan
streams#
xadd, xlen, xrange, xrevrange, xread, xgroupCreate, xgroupDestroy, xgroupCreateConsumer, xgroupDelConsumer, xreadgroup, xack, xpending, xpendingRange, xautoclaim, xclaim, xtrim, xdel, xinfo
keys#
del, unlink, exists, expire, expireAt, ttl, pttl, persist, rename, renameNx, type, scan, keys
design#
- tagged unions:
Value = union(enum)for all RESP types - distinct errors:
ConnectionError,ProtocolError,CommandError - buffer ownership: client owns read buffer; slices valid until next command
- modular commands: each data type in its own file
error handling#
const result = client.strings().get("key") catch |err| switch (err) {
error.ConnectionRefused => { ... },
error.Timeout => { ... },
error.WrongType => { ... },
else => return err,
};
building#
zig build test # run tests
zig build run # run example (requires redis on localhost:6379)
integration#
zig fetch --save https://tangled.sh/@zzstoatzz.io/redis/archive/main
then in build.zig:
const redis_dep = b.dependency("redis", .{ .target = target, .optimize = optimize });
exe.root_module.addImport("redis", redis_dep.module("redis"));