1 package redis
2
3 import (
4 "context"
5 "time"
6
7 "github.com/redis/go-redis/v9/internal/hashtag"
8 )
9
10 type GenericCmdable interface {
11 Del(ctx context.Context, keys ...string) *IntCmd
12 Dump(ctx context.Context, key string) *StringCmd
13 Exists(ctx context.Context, keys ...string) *IntCmd
14 Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
15 ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
16 ExpireTime(ctx context.Context, key string) *DurationCmd
17 ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd
18 ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd
19 ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd
20 ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd
21 Keys(ctx context.Context, pattern string) *StringSliceCmd
22 Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd
23 Move(ctx context.Context, key string, db int) *BoolCmd
24 ObjectFreq(ctx context.Context, key string) *IntCmd
25 ObjectRefCount(ctx context.Context, key string) *IntCmd
26 ObjectEncoding(ctx context.Context, key string) *StringCmd
27 ObjectIdleTime(ctx context.Context, key string) *DurationCmd
28 Persist(ctx context.Context, key string) *BoolCmd
29 PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
30 PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
31 PExpireTime(ctx context.Context, key string) *DurationCmd
32 PTTL(ctx context.Context, key string) *DurationCmd
33 RandomKey(ctx context.Context) *StringCmd
34 Rename(ctx context.Context, key, newkey string) *StatusCmd
35 RenameNX(ctx context.Context, key, newkey string) *BoolCmd
36 Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
37 RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
38 Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd
39 SortRO(ctx context.Context, key string, sort *Sort) *StringSliceCmd
40 SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd
41 SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd
42 Touch(ctx context.Context, keys ...string) *IntCmd
43 TTL(ctx context.Context, key string) *DurationCmd
44 Type(ctx context.Context, key string) *StatusCmd
45 Copy(ctx context.Context, sourceKey string, destKey string, db int, replace bool) *IntCmd
46
47 Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd
48 ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd
49 }
50
51 func (c cmdable) Del(ctx context.Context, keys ...string) *IntCmd {
52 args := make([]interface{}, 1+len(keys))
53 args[0] = "del"
54 for i, key := range keys {
55 args[1+i] = key
56 }
57 cmd := NewIntCmd(ctx, args...)
58 _ = c(ctx, cmd)
59 return cmd
60 }
61
62 func (c cmdable) Unlink(ctx context.Context, keys ...string) *IntCmd {
63 args := make([]interface{}, 1+len(keys))
64 args[0] = "unlink"
65 for i, key := range keys {
66 args[1+i] = key
67 }
68 cmd := NewIntCmd(ctx, args...)
69 _ = c(ctx, cmd)
70 return cmd
71 }
72
73 func (c cmdable) Dump(ctx context.Context, key string) *StringCmd {
74 cmd := NewStringCmd(ctx, "dump", key)
75 _ = c(ctx, cmd)
76 return cmd
77 }
78
79 func (c cmdable) Exists(ctx context.Context, keys ...string) *IntCmd {
80 args := make([]interface{}, 1+len(keys))
81 args[0] = "exists"
82 for i, key := range keys {
83 args[1+i] = key
84 }
85 cmd := NewIntCmd(ctx, args...)
86 _ = c(ctx, cmd)
87 return cmd
88 }
89
90 func (c cmdable) Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
91 return c.expire(ctx, key, expiration, "")
92 }
93
94 func (c cmdable) ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
95 return c.expire(ctx, key, expiration, "NX")
96 }
97
98 func (c cmdable) ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
99 return c.expire(ctx, key, expiration, "XX")
100 }
101
102 func (c cmdable) ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
103 return c.expire(ctx, key, expiration, "GT")
104 }
105
106 func (c cmdable) ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
107 return c.expire(ctx, key, expiration, "LT")
108 }
109
110 func (c cmdable) expire(
111 ctx context.Context, key string, expiration time.Duration, mode string,
112 ) *BoolCmd {
113 args := make([]interface{}, 3, 4)
114 args[0] = "expire"
115 args[1] = key
116 args[2] = formatSec(ctx, expiration)
117 if mode != "" {
118 args = append(args, mode)
119 }
120
121 cmd := NewBoolCmd(ctx, args...)
122 _ = c(ctx, cmd)
123 return cmd
124 }
125
126 func (c cmdable) ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd {
127 cmd := NewBoolCmd(ctx, "expireat", key, tm.Unix())
128 _ = c(ctx, cmd)
129 return cmd
130 }
131
132 func (c cmdable) ExpireTime(ctx context.Context, key string) *DurationCmd {
133 cmd := NewDurationCmd(ctx, time.Second, "expiretime", key)
134 _ = c(ctx, cmd)
135 return cmd
136 }
137
138 func (c cmdable) Keys(ctx context.Context, pattern string) *StringSliceCmd {
139 cmd := NewStringSliceCmd(ctx, "keys", pattern)
140 _ = c(ctx, cmd)
141 return cmd
142 }
143
144 func (c cmdable) Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd {
145 cmd := NewStatusCmd(
146 ctx,
147 "migrate",
148 host,
149 port,
150 key,
151 db,
152 formatMs(ctx, timeout),
153 )
154 cmd.setReadTimeout(timeout)
155 _ = c(ctx, cmd)
156 return cmd
157 }
158
159 func (c cmdable) Move(ctx context.Context, key string, db int) *BoolCmd {
160 cmd := NewBoolCmd(ctx, "move", key, db)
161 _ = c(ctx, cmd)
162 return cmd
163 }
164
165 func (c cmdable) ObjectFreq(ctx context.Context, key string) *IntCmd {
166 cmd := NewIntCmd(ctx, "object", "freq", key)
167 _ = c(ctx, cmd)
168 return cmd
169 }
170
171 func (c cmdable) ObjectRefCount(ctx context.Context, key string) *IntCmd {
172 cmd := NewIntCmd(ctx, "object", "refcount", key)
173 _ = c(ctx, cmd)
174 return cmd
175 }
176
177 func (c cmdable) ObjectEncoding(ctx context.Context, key string) *StringCmd {
178 cmd := NewStringCmd(ctx, "object", "encoding", key)
179 _ = c(ctx, cmd)
180 return cmd
181 }
182
183 func (c cmdable) ObjectIdleTime(ctx context.Context, key string) *DurationCmd {
184 cmd := NewDurationCmd(ctx, time.Second, "object", "idletime", key)
185 _ = c(ctx, cmd)
186 return cmd
187 }
188
189 func (c cmdable) Persist(ctx context.Context, key string) *BoolCmd {
190 cmd := NewBoolCmd(ctx, "persist", key)
191 _ = c(ctx, cmd)
192 return cmd
193 }
194
195 func (c cmdable) PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
196 cmd := NewBoolCmd(ctx, "pexpire", key, formatMs(ctx, expiration))
197 _ = c(ctx, cmd)
198 return cmd
199 }
200
201 func (c cmdable) PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd {
202 cmd := NewBoolCmd(
203 ctx,
204 "pexpireat",
205 key,
206 tm.UnixNano()/int64(time.Millisecond),
207 )
208 _ = c(ctx, cmd)
209 return cmd
210 }
211
212 func (c cmdable) PExpireTime(ctx context.Context, key string) *DurationCmd {
213 cmd := NewDurationCmd(ctx, time.Millisecond, "pexpiretime", key)
214 _ = c(ctx, cmd)
215 return cmd
216 }
217
218 func (c cmdable) PTTL(ctx context.Context, key string) *DurationCmd {
219 cmd := NewDurationCmd(ctx, time.Millisecond, "pttl", key)
220 _ = c(ctx, cmd)
221 return cmd
222 }
223
224 func (c cmdable) RandomKey(ctx context.Context) *StringCmd {
225 cmd := NewStringCmd(ctx, "randomkey")
226 _ = c(ctx, cmd)
227 return cmd
228 }
229
230 func (c cmdable) Rename(ctx context.Context, key, newkey string) *StatusCmd {
231 cmd := NewStatusCmd(ctx, "rename", key, newkey)
232 _ = c(ctx, cmd)
233 return cmd
234 }
235
236 func (c cmdable) RenameNX(ctx context.Context, key, newkey string) *BoolCmd {
237 cmd := NewBoolCmd(ctx, "renamenx", key, newkey)
238 _ = c(ctx, cmd)
239 return cmd
240 }
241
242 func (c cmdable) Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd {
243 cmd := NewStatusCmd(
244 ctx,
245 "restore",
246 key,
247 formatMs(ctx, ttl),
248 value,
249 )
250 _ = c(ctx, cmd)
251 return cmd
252 }
253
254 func (c cmdable) RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd {
255 cmd := NewStatusCmd(
256 ctx,
257 "restore",
258 key,
259 formatMs(ctx, ttl),
260 value,
261 "replace",
262 )
263 _ = c(ctx, cmd)
264 return cmd
265 }
266
267 type Sort struct {
268 By string
269 Offset, Count int64
270 Get []string
271 Order string
272 Alpha bool
273 }
274
275 func (sort *Sort) args(command, key string) []interface{} {
276 args := []interface{}{command, key}
277
278 if sort.By != "" {
279 args = append(args, "by", sort.By)
280 }
281 if sort.Offset != 0 || sort.Count != 0 {
282 args = append(args, "limit", sort.Offset, sort.Count)
283 }
284 for _, get := range sort.Get {
285 args = append(args, "get", get)
286 }
287 if sort.Order != "" {
288 args = append(args, sort.Order)
289 }
290 if sort.Alpha {
291 args = append(args, "alpha")
292 }
293 return args
294 }
295
296 func (c cmdable) SortRO(ctx context.Context, key string, sort *Sort) *StringSliceCmd {
297 cmd := NewStringSliceCmd(ctx, sort.args("sort_ro", key)...)
298 _ = c(ctx, cmd)
299 return cmd
300 }
301
302 func (c cmdable) Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd {
303 cmd := NewStringSliceCmd(ctx, sort.args("sort", key)...)
304 _ = c(ctx, cmd)
305 return cmd
306 }
307
308 func (c cmdable) SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd {
309 args := sort.args("sort", key)
310 if store != "" {
311 args = append(args, "store", store)
312 }
313 cmd := NewIntCmd(ctx, args...)
314 _ = c(ctx, cmd)
315 return cmd
316 }
317
318 func (c cmdable) SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd {
319 cmd := NewSliceCmd(ctx, sort.args("sort", key)...)
320 _ = c(ctx, cmd)
321 return cmd
322 }
323
324 func (c cmdable) Touch(ctx context.Context, keys ...string) *IntCmd {
325 args := make([]interface{}, len(keys)+1)
326 args[0] = "touch"
327 for i, key := range keys {
328 args[i+1] = key
329 }
330 cmd := NewIntCmd(ctx, args...)
331 _ = c(ctx, cmd)
332 return cmd
333 }
334
335 func (c cmdable) TTL(ctx context.Context, key string) *DurationCmd {
336 cmd := NewDurationCmd(ctx, time.Second, "ttl", key)
337 _ = c(ctx, cmd)
338 return cmd
339 }
340
341 func (c cmdable) Type(ctx context.Context, key string) *StatusCmd {
342 cmd := NewStatusCmd(ctx, "type", key)
343 _ = c(ctx, cmd)
344 return cmd
345 }
346
347 func (c cmdable) Copy(ctx context.Context, sourceKey, destKey string, db int, replace bool) *IntCmd {
348 args := []interface{}{"copy", sourceKey, destKey, "DB", db}
349 if replace {
350 args = append(args, "REPLACE")
351 }
352 cmd := NewIntCmd(ctx, args...)
353 _ = c(ctx, cmd)
354 return cmd
355 }
356
357
358
359 func (c cmdable) Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd {
360 args := []interface{}{"scan", cursor}
361 if match != "" {
362 args = append(args, "match", match)
363 }
364 if count > 0 {
365 args = append(args, "count", count)
366 }
367 cmd := NewScanCmd(ctx, c, args...)
368 if hashtag.Present(match) {
369 cmd.SetFirstKeyPos(3)
370 }
371 _ = c(ctx, cmd)
372 return cmd
373 }
374
375 func (c cmdable) ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd {
376 args := []interface{}{"scan", cursor}
377 if match != "" {
378 args = append(args, "match", match)
379 }
380 if count > 0 {
381 args = append(args, "count", count)
382 }
383 if keyType != "" {
384 args = append(args, "type", keyType)
385 }
386 cmd := NewScanCmd(ctx, c, args...)
387 if hashtag.Present(match) {
388 cmd.SetFirstKeyPos(3)
389 }
390 _ = c(ctx, cmd)
391 return cmd
392 }
393
View as plain text