this repo has no description
1//! Redis client usage examples
2//!
3//! Run with: zig build run
4//! Requires a Redis server running on localhost:6379
5
6const std = @import("std");
7const redis = @import("redis");
8
9pub fn main() !void {
10 var gpa: std.heap.DebugAllocator(.{}) = .init;
11 defer _ = gpa.deinit();
12 const allocator = gpa.allocator();
13
14 // Connect to Redis
15 var client = redis.Client.connect(std.Options.debug_io, allocator, "localhost", 6379) catch |err| {
16 std.debug.print("Failed to connect: {}\n", .{err});
17 return;
18 };
19 defer client.close();
20
21 std.debug.print("Connected to Redis\n\n", .{});
22
23 // String operations
24 stringExamples(&client);
25
26 // Hash operations
27 hashExamples(&client);
28
29 // List operations
30 listExamples(&client);
31
32 // Set operations
33 setExamples(&client);
34
35 // Sorted set operations
36 sortedSetExamples(&client);
37
38 // Stream operations
39 streamExamples(&client);
40
41 std.debug.print("\nAll examples completed.\n", .{});
42}
43
44fn stringExamples(client: *redis.Client) void {
45 std.debug.print("=== String Operations ===\n", .{});
46 var str = client.strings();
47
48 // SET and GET
49 str.set("greeting", "hello, redis!") catch return;
50 if (str.get("greeting") catch null) |val| {
51 std.debug.print("GET greeting: {s}\n", .{val});
52 }
53
54 // INCR
55 _ = str.set("counter", "0") catch return;
56 const count = str.incr("counter") catch return;
57 std.debug.print("INCR counter: {d}\n", .{count});
58
59 // MSET/MGET
60 str.mset(&.{
61 .{ "key1", "value1" },
62 .{ "key2", "value2" },
63 }) catch return;
64 const values = str.mget(&.{ "key1", "key2", "missing" }) catch return;
65 std.debug.print("MGET: ", .{});
66 for (values) |v| {
67 if (v.asString()) |s| {
68 std.debug.print("{s} ", .{s});
69 } else {
70 std.debug.print("(nil) ", .{});
71 }
72 }
73 std.debug.print("\n\n", .{});
74}
75
76fn hashExamples(client: *redis.Client) void {
77 std.debug.print("=== Hash Operations ===\n", .{});
78 var hash = client.hashes();
79
80 // HSET multiple fields
81 _ = hash.hsetMulti("user:1", &.{
82 .{ "name", "alice" },
83 .{ "email", "alice@example.com" },
84 .{ "score", "100" },
85 }) catch return;
86
87 // HGET single field
88 if (hash.hget("user:1", "name") catch null) |name| {
89 std.debug.print("HGET user:1 name: {s}\n", .{name});
90 }
91
92 // HINCRBY
93 const new_score = hash.hincrBy("user:1", "score", 50) catch return;
94 std.debug.print("HINCRBY user:1 score 50: {d}\n", .{new_score});
95
96 // HGETALL
97 const all = hash.hgetAll("user:1") catch return;
98 std.debug.print("HGETALL user:1: ", .{});
99 var i: usize = 0;
100 while (i + 1 < all.len) : (i += 2) {
101 const field = all[i].asString() orelse continue;
102 const value = all[i + 1].asString() orelse continue;
103 std.debug.print("{s}={s} ", .{ field, value });
104 }
105 std.debug.print("\n\n", .{});
106}
107
108fn listExamples(client: *redis.Client) void {
109 std.debug.print("=== List Operations ===\n", .{});
110 var list = client.lists();
111
112 // Clear and populate list
113 var keys = client.keys();
114 _ = keys.del(&.{"tasks"}) catch {};
115 _ = list.rpush("tasks", &.{ "task1", "task2", "task3" }) catch return;
116
117 // LRANGE
118 const tasks = list.lrange("tasks", 0, -1) catch return;
119 std.debug.print("LRANGE tasks 0 -1: ", .{});
120 for (tasks) |t| {
121 if (t.asString()) |s| {
122 std.debug.print("{s} ", .{s});
123 }
124 }
125 std.debug.print("\n", .{});
126
127 // LPOP
128 if (list.lpop("tasks") catch null) |first| {
129 std.debug.print("LPOP tasks: {s}\n", .{first});
130 }
131
132 std.debug.print("\n", .{});
133}
134
135fn setExamples(client: *redis.Client) void {
136 std.debug.print("=== Set Operations ===\n", .{});
137 var s = client.sets();
138
139 // SADD
140 _ = s.sadd("tags:post1", &.{ "redis", "database", "nosql" }) catch return;
141 _ = s.sadd("tags:post2", &.{ "redis", "cache", "performance" }) catch return;
142
143 // SMEMBERS
144 const members = s.smembers("tags:post1") catch return;
145 std.debug.print("SMEMBERS tags:post1: ", .{});
146 for (members) |m| {
147 if (m.asString()) |str| {
148 std.debug.print("{s} ", .{str});
149 }
150 }
151 std.debug.print("\n", .{});
152
153 // SINTER
154 const common = s.sinter(&.{ "tags:post1", "tags:post2" }) catch return;
155 std.debug.print("SINTER tags:post1 tags:post2: ", .{});
156 for (common) |c| {
157 if (c.asString()) |str| {
158 std.debug.print("{s} ", .{str});
159 }
160 }
161 std.debug.print("\n\n", .{});
162}
163
164fn sortedSetExamples(client: *redis.Client) void {
165 std.debug.print("=== Sorted Set Operations ===\n", .{});
166 var zset = client.sortedSets();
167
168 // Clear and add scores
169 var keys = client.keys();
170 _ = keys.del(&.{"leaderboard"}) catch {};
171 _ = zset.zaddMulti("leaderboard", .{}, &.{
172 .{ .score = 100, .member = "alice" },
173 .{ .score = 85, .member = "bob" },
174 .{ .score = 92, .member = "charlie" },
175 }) catch return;
176
177 // ZRANGE with scores (top 3)
178 const top = zset.zrangeWithScores("leaderboard", 0, -1, .desc) catch return;
179 std.debug.print("Leaderboard (high to low):\n", .{});
180 var i: usize = 0;
181 while (i + 1 < top.len) : (i += 2) {
182 const member = top[i].asString() orelse continue;
183 const score = top[i + 1].asString() orelse continue;
184 std.debug.print(" {s}: {s}\n", .{ member, score });
185 }
186
187 // ZSCORE
188 if (zset.zscore("leaderboard", "bob") catch null) |score| {
189 std.debug.print("ZSCORE leaderboard bob: {d}\n", .{score});
190 }
191
192 std.debug.print("\n", .{});
193}
194
195fn streamExamples(client: *redis.Client) void {
196 std.debug.print("=== Stream Operations ===\n", .{});
197 var stream = client.streams();
198
199 // Delete and recreate stream
200 var keys = client.keys();
201 _ = keys.del(&.{"events"}) catch {};
202
203 // XADD
204 const id1 = stream.xadd("events", .auto, &.{
205 .{ "type", "login" },
206 .{ "user", "alice" },
207 }) catch return;
208 std.debug.print("XADD events: {s}\n", .{id1});
209
210 const id2 = stream.xadd("events", .auto, &.{
211 .{ "type", "purchase" },
212 .{ "user", "alice" },
213 .{ "amount", "99.99" },
214 }) catch return;
215 std.debug.print("XADD events: {s}\n", .{id2});
216
217 // XLEN
218 const len = stream.xlen("events") catch return;
219 std.debug.print("XLEN events: {d}\n", .{len});
220
221 // XRANGE
222 const entries = stream.xrange("events", "-", "+", null) catch return;
223 std.debug.print("XRANGE events:\n", .{});
224 for (entries) |entry| {
225 std.debug.print(" {s}: ", .{entry.id});
226 for (entry.fields) |field| {
227 std.debug.print("{s}={s} ", .{ field.field, field.value });
228 }
229 std.debug.print("\n", .{});
230 }
231
232 // Consumer group example
233 _ = stream.xgroupDestroy("events", "workers") catch {}; // cleanup
234 stream.xgroupCreate("events", "workers", "0") catch |err| {
235 std.debug.print("XGROUP CREATE error: {}\n", .{err});
236 return;
237 };
238 std.debug.print("Created consumer group 'workers'\n", .{});
239
240 std.debug.print("\n", .{});
241}