//! Redis client usage examples //! //! Run with: zig build run //! Requires a Redis server running on localhost:6379 const std = @import("std"); const redis = @import("redis"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); // Connect to Redis var client = redis.Client.connect(allocator, "localhost", 6379) catch |err| { std.debug.print("Failed to connect: {}\n", .{err}); return; }; defer client.close(); std.debug.print("Connected to Redis\n\n", .{}); // String operations stringExamples(&client); // Hash operations hashExamples(&client); // List operations listExamples(&client); // Set operations setExamples(&client); // Sorted set operations sortedSetExamples(&client); // Stream operations streamExamples(&client); std.debug.print("\nAll examples completed.\n", .{}); } fn stringExamples(client: *redis.Client) void { std.debug.print("=== String Operations ===\n", .{}); var str = client.strings(); // SET and GET str.set("greeting", "hello, redis!") catch return; if (str.get("greeting") catch null) |val| { std.debug.print("GET greeting: {s}\n", .{val}); } // INCR _ = str.set("counter", "0") catch return; const count = str.incr("counter") catch return; std.debug.print("INCR counter: {d}\n", .{count}); // MSET/MGET str.mset(&.{ .{ "key1", "value1" }, .{ "key2", "value2" }, }) catch return; const values = str.mget(&.{ "key1", "key2", "missing" }) catch return; std.debug.print("MGET: ", .{}); for (values) |v| { if (v.asString()) |s| { std.debug.print("{s} ", .{s}); } else { std.debug.print("(nil) ", .{}); } } std.debug.print("\n\n", .{}); } fn hashExamples(client: *redis.Client) void { std.debug.print("=== Hash Operations ===\n", .{}); var hash = client.hashes(); // HSET multiple fields _ = hash.hset("user:1", &.{ .{ "name", "alice" }, .{ "email", "alice@example.com" }, .{ "score", "100" }, }) catch return; // HGET single field if (hash.hget("user:1", "name") catch null) |name| { std.debug.print("HGET user:1 name: {s}\n", .{name}); } // HINCRBY const new_score = hash.hincrBy("user:1", "score", 50) catch return; std.debug.print("HINCRBY user:1 score 50: {d}\n", .{new_score}); // HGETALL const all = hash.hgetAll("user:1") catch return; std.debug.print("HGETALL user:1: ", .{}); var i: usize = 0; while (i + 1 < all.len) : (i += 2) { const field = all[i].asString() orelse continue; const value = all[i + 1].asString() orelse continue; std.debug.print("{s}={s} ", .{ field, value }); } std.debug.print("\n\n", .{}); } fn listExamples(client: *redis.Client) void { std.debug.print("=== List Operations ===\n", .{}); var list = client.lists(); // Clear and populate list _ = client.keys().del(&.{"tasks"}) catch {}; _ = list.rpush("tasks", &.{ "task1", "task2", "task3" }) catch return; // LRANGE const tasks = list.lrange("tasks", 0, -1) catch return; std.debug.print("LRANGE tasks 0 -1: ", .{}); for (tasks) |t| { if (t.asString()) |s| { std.debug.print("{s} ", .{s}); } } std.debug.print("\n", .{}); // LPOP if (list.lpop("tasks") catch null) |first| { std.debug.print("LPOP tasks: {s}\n", .{first}); } std.debug.print("\n", .{}); } fn setExamples(client: *redis.Client) void { std.debug.print("=== Set Operations ===\n", .{}); var s = client.sets(); // SADD _ = s.sadd("tags:post1", &.{ "redis", "database", "nosql" }) catch return; _ = s.sadd("tags:post2", &.{ "redis", "cache", "performance" }) catch return; // SMEMBERS const members = s.smembers("tags:post1") catch return; std.debug.print("SMEMBERS tags:post1: ", .{}); for (members) |m| { if (m.asString()) |str| { std.debug.print("{s} ", .{str}); } } std.debug.print("\n", .{}); // SINTER const common = s.sinter(&.{ "tags:post1", "tags:post2" }) catch return; std.debug.print("SINTER tags:post1 tags:post2: ", .{}); for (common) |c| { if (c.asString()) |str| { std.debug.print("{s} ", .{str}); } } std.debug.print("\n\n", .{}); } fn sortedSetExamples(client: *redis.Client) void { std.debug.print("=== Sorted Set Operations ===\n", .{}); var zset = client.sortedSets(); // Clear and add scores _ = client.keys().del(&.{"leaderboard"}) catch {}; _ = zset.zadd("leaderboard", &.{ .{ .score = 100, .member = "alice" }, .{ .score = 85, .member = "bob" }, .{ .score = 92, .member = "charlie" }, }, .{}) catch return; // ZRANGE with scores (top 3) const top = zset.zrangeWithScores("leaderboard", 0, -1, .{ .rev = true }) catch return; std.debug.print("Leaderboard (high to low):\n", .{}); for (top) |entry| { std.debug.print(" {s}: {d}\n", .{ entry.member, entry.score }); } // ZSCORE if (zset.zscore("leaderboard", "bob") catch null) |score| { std.debug.print("ZSCORE leaderboard bob: {d}\n", .{score}); } std.debug.print("\n", .{}); } fn streamExamples(client: *redis.Client) void { std.debug.print("=== Stream Operations ===\n", .{}); var stream = client.streams(); // Delete and recreate stream _ = client.keys().del(&.{"events"}) catch {}; // XADD const id1 = stream.xadd("events", .auto, &.{ .{ "type", "login" }, .{ "user", "alice" }, }) catch return; std.debug.print("XADD events: {s}\n", .{id1}); const id2 = stream.xadd("events", .auto, &.{ .{ "type", "purchase" }, .{ "user", "alice" }, .{ "amount", "99.99" }, }) catch return; std.debug.print("XADD events: {s}\n", .{id2}); // XLEN const len = stream.xlen("events") catch return; std.debug.print("XLEN events: {d}\n", .{len}); // XRANGE const entries = stream.xrange("events", "-", "+", null) catch return; std.debug.print("XRANGE events:\n", .{}); for (entries) |entry| { std.debug.print(" {s}: ", .{entry.id}); for (entry.fields) |field| { std.debug.print("{s}={s} ", .{ field.name, field.value }); } std.debug.print("\n", .{}); } // Consumer group example _ = stream.xgroupDestroy("events", "workers") catch {}; // cleanup stream.xgroupCreate("events", "workers", "0", true) catch |err| { std.debug.print("XGROUP CREATE error: {}\n", .{err}); return; }; std.debug.print("Created consumer group 'workers'\n", .{}); std.debug.print("\n", .{}); }