fred/commands/interfaces/
keys.rs

1use crate::{
2  commands,
3  error::Error,
4  interfaces::{ClientLike, FredResult},
5  types::{scan::ScanType, Expiration, ExpireOptions, FromValue, Key, Map, MultipleKeys, SetOptions, Value},
6};
7use bytes_utils::Str;
8use fred_macros::rm_send_if;
9use futures::Future;
10use std::convert::TryInto;
11
12/// Functions that implement the generic [keys](https://redis.io/commands#generic) interface.
13#[rm_send_if(feature = "glommio")]
14pub trait KeysInterface: ClientLike + Sized {
15  /// Marks the given keys to be watched for conditional execution of a transaction.
16  ///
17  /// This should usually be used with an [ExclusivePool](crate::clients::ExclusivePool).
18  ///
19  /// <https://redis.io/commands/watch>
20  fn watch<K>(&self, keys: K) -> impl Future<Output = FredResult<()>> + Send
21  where
22    K: Into<MultipleKeys> + Send,
23  {
24    async move {
25      into!(keys);
26      commands::keys::watch(self, keys).await
27    }
28  }
29
30  /// Flushes all the previously watched keys for a transaction.
31  ///
32  /// <https://redis.io/commands/unwatch>
33  fn unwatch(&self) -> impl Future<Output = FredResult<()>> + Send {
34    async move { commands::keys::unwatch(self).await }
35  }
36
37  /// Return a random key from the currently selected database.
38  ///
39  /// <https://redis.io/commands/randomkey>
40  fn randomkey<R>(&self) -> impl Future<Output = FredResult<R>> + Send
41  where
42    R: FromValue,
43  {
44    async move { commands::keys::randomkey(self).await?.convert() }
45  }
46
47  /// This command copies the value stored at the source key to the destination key.
48  ///
49  /// <https://redis.io/commands/copy>
50  fn copy<R, S, D>(
51    &self,
52    source: S,
53    destination: D,
54    db: Option<u8>,
55    replace: bool,
56  ) -> impl Future<Output = FredResult<R>> + Send
57  where
58    R: FromValue,
59    S: Into<Key> + Send,
60    D: Into<Key> + Send,
61  {
62    async move {
63      into!(source, destination);
64      commands::keys::copy(self, source, destination, db, replace)
65        .await?
66        .convert()
67    }
68  }
69
70  /// Serialize the value stored at `key` in a Redis-specific format and return it as bulk string.
71  ///
72  /// <https://redis.io/commands/dump>
73  fn dump<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
74  where
75    R: FromValue,
76    K: Into<Key> + Send,
77  {
78    async move {
79      into!(key);
80      commands::keys::dump(self, key).await?.convert()
81    }
82  }
83
84  /// Returns the string representation of the type of the value stored at key. The different types that can be
85  /// returned are: string, list, set, zset, hash and stream.
86  ///
87  /// <https://redis.io/docs/latest/commands/type/>
88  fn r#type<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
89  where
90    R: FromValue,
91    K: Into<Key> + Send,
92  {
93    async move {
94      into!(key);
95      commands::keys::r#type(self, key).await?.convert()
96    }
97  }
98
99  /// Create a key associated with a value that is obtained by deserializing the provided serialized value
100  ///
101  /// <https://redis.io/commands/restore>
102  fn restore<R, K>(
103    &self,
104    key: K,
105    ttl: i64,
106    serialized: Value,
107    replace: bool,
108    absttl: bool,
109    idletime: Option<i64>,
110    frequency: Option<i64>,
111  ) -> impl Future<Output = FredResult<R>> + Send
112  where
113    R: FromValue,
114    K: Into<Key> + Send,
115  {
116    async move {
117      into!(key);
118      commands::keys::restore(self, key, ttl, serialized, replace, absttl, idletime, frequency)
119        .await?
120        .convert()
121    }
122  }
123
124  /// Set a value with optional NX|XX, EX|PX|EXAT|PXAT|KEEPTTL, and GET arguments.
125  ///
126  /// Note: the `get` flag was added in 6.2.0. Setting it as `false` works with Redis versions <=6.2.0.
127  ///
128  /// <https://redis.io/commands/set>
129  fn set<R, K, V>(
130    &self,
131    key: K,
132    value: V,
133    expire: Option<Expiration>,
134    options: Option<SetOptions>,
135    get: bool,
136  ) -> impl Future<Output = FredResult<R>> + Send
137  where
138    R: FromValue,
139    K: Into<Key> + Send,
140    V: TryInto<Value> + Send,
141    V::Error: Into<Error> + Send,
142  {
143    async move {
144      into!(key);
145      try_into!(value);
146      commands::keys::set(self, key, value, expire, options, get)
147        .await?
148        .convert()
149    }
150  }
151
152  /// Sets `key` to `value` if `key` does not exist.
153  ///
154  /// Note: the command is regarded as deprecated since Redis 2.6.12.
155  ///
156  /// <https://redis.io/commands/setnx>
157  fn setnx<R, K, V>(&self, key: K, value: V) -> impl Future<Output = FredResult<R>> + Send
158  where
159    R: FromValue,
160    K: Into<Key> + Send,
161    V: TryInto<Value> + Send,
162    V::Error: Into<Error> + Send,
163  {
164    async move {
165      into!(key);
166      try_into!(value);
167      commands::keys::setnx(self, key, value).await?.convert()
168    }
169  }
170
171  /// Read a value from the server.
172  ///
173  /// <https://redis.io/commands/get>
174  fn get<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
175  where
176    R: FromValue,
177    K: Into<Key> + Send,
178  {
179    async move {
180      into!(key);
181      commands::keys::get(self, key).await?.convert()
182    }
183  }
184
185  /// Returns the substring of the string value stored at `key` with offsets `start` and `end` (both inclusive).
186  ///
187  /// Note: Command formerly called SUBSTR in Redis verison <=2.0.
188  ///
189  /// <https://redis.io/commands/getrange>
190  fn getrange<R, K>(&self, key: K, start: usize, end: usize) -> impl Future<Output = FredResult<R>> + Send
191  where
192    R: FromValue,
193    K: Into<Key> + Send,
194  {
195    async move {
196      into!(key);
197      commands::keys::getrange(self, key, start, end).await?.convert()
198    }
199  }
200
201  /// Overwrites part of the string stored at `key`, starting at the specified `offset`, for the entire length of
202  /// `value`.
203  ///
204  /// <https://redis.io/commands/setrange>
205  fn setrange<R, K, V>(&self, key: K, offset: u32, value: V) -> impl Future<Output = FredResult<R>> + Send
206  where
207    R: FromValue,
208    K: Into<Key> + Send,
209    V: TryInto<Value> + Send,
210    V::Error: Into<Error> + Send,
211  {
212    async move {
213      into!(key);
214      try_into!(value);
215      commands::keys::setrange(self, key, offset, value).await?.convert()
216    }
217  }
218
219  /// Atomically sets `key` to `value` and returns the old value stored at `key`.
220  ///
221  /// Returns an error if `key` does not hold string value. Returns nil if `key` does not exist.
222  ///
223  /// <https://redis.io/commands/getset>
224  fn getset<R, K, V>(&self, key: K, value: V) -> impl Future<Output = FredResult<R>> + Send
225  where
226    R: FromValue,
227    K: Into<Key> + Send,
228    V: TryInto<Value> + Send,
229    V::Error: Into<Error> + Send,
230  {
231    async move {
232      into!(key);
233      try_into!(value);
234      commands::keys::getset(self, key, value).await?.convert()
235    }
236  }
237
238  /// Get the value of key and delete the key. This command is similar to GET, except for the fact that it also
239  /// deletes the key on success (if and only if the key's value type is a string).
240  ///
241  /// <https://redis.io/commands/getdel>
242  fn getdel<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
243  where
244    R: FromValue,
245    K: Into<Key> + Send,
246  {
247    async move {
248      into!(key);
249      commands::keys::getdel(self, key).await?.convert()
250    }
251  }
252
253  /// Returns the length of the string value stored at key. An error is returned when key holds a non-string value.
254  ///
255  /// <https://redis.io/commands/strlen>
256  fn strlen<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
257  where
258    R: FromValue,
259    K: Into<Key> + Send,
260  {
261    async move {
262      into!(key);
263      commands::keys::strlen(self, key).await?.convert()
264    }
265  }
266
267  /// Removes the specified keys. A key is ignored if it does not exist.
268  ///
269  /// Returns the number of keys removed.
270  ///
271  /// <https://redis.io/commands/del>
272  fn del<R, K>(&self, keys: K) -> impl Future<Output = FredResult<R>> + Send
273  where
274    R: FromValue,
275    K: Into<MultipleKeys> + Send,
276  {
277    async move {
278      into!(keys);
279      commands::keys::del(self, keys).await?.convert()
280    }
281  }
282
283  /// Unlinks the specified keys. A key is ignored if it does not exist
284  ///
285  /// Returns the number of keys removed.
286  ///
287  /// <https://redis.io/commands/del>
288  fn unlink<R, K>(&self, keys: K) -> impl Future<Output = FredResult<R>> + Send
289  where
290    R: FromValue,
291    K: Into<MultipleKeys> + Send,
292  {
293    async move {
294      into!(keys);
295      commands::keys::unlink(self, keys).await?.convert()
296    }
297  }
298
299  /// Renames `source` key to `destination`.
300  ///
301  /// Returns an error when `source` does not exist. If `destination` exists, it gets overwritten.
302  ///
303  /// <https://redis.io/commands/rename>
304  fn rename<R, S, D>(&self, source: S, destination: D) -> impl Future<Output = FredResult<R>> + Send
305  where
306    R: FromValue,
307    S: Into<Key> + Send,
308    D: Into<Key> + Send,
309  {
310    async move {
311      into!(source);
312      into!(destination);
313      commands::keys::rename(self, source, destination).await?.convert()
314    }
315  }
316
317  /// Renames `source` key to `destination` if `destination` does not yet exist.
318  ///
319  /// Returns an error when `source` does not exist.
320  ///
321  /// <https://redis.io/commands/renamenx>
322  fn renamenx<R, S, D>(&self, source: S, destination: D) -> impl Future<Output = FredResult<R>> + Send
323  where
324    R: FromValue,
325    S: Into<Key> + Send,
326    D: Into<Key> + Send,
327  {
328    async move {
329      into!(source);
330      into!(destination);
331      commands::keys::renamenx(self, source, destination).await?.convert()
332    }
333  }
334
335  /// Append `value` to `key` if it's a string.
336  ///
337  /// <https://redis.io/commands/append/>
338  fn append<R, K, V>(&self, key: K, value: V) -> impl Future<Output = FredResult<R>> + Send
339  where
340    R: FromValue,
341    K: Into<Key> + Send,
342    V: TryInto<Value> + Send,
343    V::Error: Into<Error> + Send,
344  {
345    async move {
346      into!(key);
347      try_into!(value);
348      commands::keys::append(self, key, value).await?.convert()
349    }
350  }
351
352  /// Returns the values of all specified keys. For every key that does not hold a string value or does not exist, the
353  /// special value nil is returned.
354  ///
355  /// <https://redis.io/commands/mget>
356  fn mget<R, K>(&self, keys: K) -> impl Future<Output = FredResult<R>> + Send
357  where
358    R: FromValue,
359    K: Into<MultipleKeys> + Send,
360  {
361    async move {
362      into!(keys);
363      commands::keys::mget(self, keys).await?.convert()
364    }
365  }
366
367  /// Sets the given keys to their respective values.
368  ///
369  /// <https://redis.io/commands/mset>
370  fn mset<V>(&self, values: V) -> impl Future<Output = FredResult<()>> + Send
371  where
372    V: TryInto<Map> + Send,
373    V::Error: Into<Error> + Send,
374  {
375    async move {
376      try_into!(values);
377      commands::keys::mset(self, values).await?.convert()
378    }
379  }
380
381  /// Sets the given keys to their respective values. MSETNX will not perform any operation at all even if just a
382  /// single key already exists.
383  ///
384  /// <https://redis.io/commands/msetnx>
385  fn msetnx<R, V>(&self, values: V) -> impl Future<Output = FredResult<R>> + Send
386  where
387    R: FromValue,
388    V: TryInto<Map> + Send,
389    V::Error: Into<Error> + Send,
390  {
391    async move {
392      try_into!(values);
393      commands::keys::msetnx(self, values).await?.convert()
394    }
395  }
396
397  /// Increments the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the
398  /// operation.
399  ///
400  /// Returns an error if the value at key is of the wrong type.
401  ///
402  /// <https://redis.io/commands/incr>
403  fn incr<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
404  where
405    R: FromValue,
406    K: Into<Key> + Send,
407  {
408    async move {
409      into!(key);
410      commands::keys::incr(self, key).await?.convert()
411    }
412  }
413
414  /// Increments the number stored at `key` by `val`. If the key does not exist, it is set to 0 before performing the
415  /// operation.
416  ///
417  /// Returns an error if the value at key is of the wrong type.
418  ///
419  /// <https://redis.io/commands/incrby>
420  fn incr_by<R, K>(&self, key: K, val: i64) -> impl Future<Output = FredResult<R>> + Send
421  where
422    R: FromValue,
423    K: Into<Key> + Send,
424  {
425    async move {
426      into!(key);
427      commands::keys::incr_by(self, key, val).await?.convert()
428    }
429  }
430
431  /// Increment the string representing a floating point number stored at key by `val`. If the key does not exist, it
432  /// is set to 0 before performing the operation.
433  ///
434  /// Returns an error if key value is the wrong type or if the current value cannot be parsed as a floating point
435  /// value.
436  ///
437  /// <https://redis.io/commands/incrbyfloat>
438  fn incr_by_float<R, K>(&self, key: K, val: f64) -> impl Future<Output = FredResult<R>> + Send
439  where
440    R: FromValue,
441    K: Into<Key> + Send,
442  {
443    async move {
444      into!(key);
445      commands::keys::incr_by_float(self, key, val).await?.convert()
446    }
447  }
448
449  /// Decrements the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the
450  /// operation.
451  ///
452  /// Returns an error if the key contains a value of the wrong type.
453  ///
454  /// <https://redis.io/commands/decr>
455  fn decr<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
456  where
457    R: FromValue,
458    K: Into<Key> + Send,
459  {
460    async move {
461      into!(key);
462      commands::keys::decr(self, key).await?.convert()
463    }
464  }
465
466  /// Decrements the number stored at `key` by `val`. If the key does not exist, it is set to 0 before performing the
467  /// operation.
468  ///
469  /// Returns an error if the key contains a value of the wrong type.
470  ///
471  /// <https://redis.io/commands/decrby>
472  fn decr_by<R, K>(&self, key: K, val: i64) -> impl Future<Output = FredResult<R>> + Send
473  where
474    R: FromValue,
475    K: Into<Key> + Send,
476  {
477    async move {
478      into!(key);
479      commands::keys::decr_by(self, key, val).await?.convert()
480    }
481  }
482
483  /// Returns the remaining time to live of a key that has a timeout, in seconds.
484  ///
485  /// <https://redis.io/commands/ttl>
486  fn ttl<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
487  where
488    R: FromValue,
489    K: Into<Key> + Send,
490  {
491    async move {
492      into!(key);
493      commands::keys::ttl(self, key).await?.convert()
494    }
495  }
496
497  /// Returns the remaining time to live of a key that has a timeout, in milliseconds.
498  ///
499  /// <https://redis.io/commands/pttl>
500  fn pttl<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
501  where
502    R: FromValue,
503    K: Into<Key> + Send,
504  {
505    async move {
506      into!(key);
507      commands::keys::pttl(self, key).await?.convert()
508    }
509  }
510
511  /// Remove the existing timeout on a key, turning the key from volatile (a key with an expiration)
512  /// to persistent (a key that will never expire as no timeout is associated).
513  ///
514  /// Returns a boolean value describing whether the timeout was removed.
515  ///
516  /// <https://redis.io/commands/persist>
517  fn persist<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
518  where
519    R: FromValue,
520    K: Into<Key> + Send,
521  {
522    async move {
523      into!(key);
524      commands::keys::persist(self, key).await?.convert()
525    }
526  }
527
528  /// Set a timeout on key. After the timeout has expired, the key will be automatically deleted.
529  ///
530  /// <https://redis.io/commands/expire>
531  fn expire<R, K>(
532    &self,
533    key: K,
534    seconds: i64,
535    options: Option<ExpireOptions>,
536  ) -> impl Future<Output = FredResult<R>> + Send
537  where
538    R: FromValue,
539    K: Into<Key> + Send,
540  {
541    async move {
542      into!(key);
543      commands::keys::expire(self, key, seconds, options).await?.convert()
544    }
545  }
546
547  /// Set a timeout on a key based on a UNIX timestamp.
548  ///
549  /// <https://redis.io/commands/expireat>
550  fn expire_at<R, K>(
551    &self,
552    key: K,
553    timestamp: i64,
554    options: Option<ExpireOptions>,
555  ) -> impl Future<Output = FredResult<R>> + Send
556  where
557    R: FromValue,
558    K: Into<Key> + Send,
559  {
560    async move {
561      into!(key);
562      commands::keys::expire_at(self, key, timestamp, options)
563        .await?
564        .convert()
565    }
566  }
567
568  /// Returns the absolute Unix timestamp (since January 1, 1970) in seconds at which the given key will expire.
569  ///
570  /// <https://redis.io/docs/latest/commands/expiretime/>
571  fn expire_time<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
572  where
573    R: FromValue,
574    K: Into<Key> + Send,
575  {
576    async move {
577      into!(key);
578      commands::keys::expire_time(self, key).await?.convert()
579    }
580  }
581
582  /// This command works exactly like EXPIRE but the time to live of the key is specified in milliseconds instead of
583  /// seconds.
584  ///
585  /// <https://redis.io/docs/latest/commands/pexpire/>
586  fn pexpire<R, K>(
587    &self,
588    key: K,
589    milliseconds: i64,
590    options: Option<ExpireOptions>,
591  ) -> impl Future<Output = FredResult<R>> + Send
592  where
593    R: FromValue,
594    K: Into<Key> + Send,
595  {
596    async move {
597      into!(key);
598      commands::keys::pexpire(self, key, milliseconds, options)
599        .await?
600        .convert()
601    }
602  }
603
604  /// PEXPIREAT has the same effect and semantic as EXPIREAT, but the Unix time at which the key will expire is
605  /// specified in milliseconds instead of seconds.
606  ///
607  /// <https://redis.io/docs/latest/commands/pexpireat/>
608  fn pexpire_at<R, K>(
609    &self,
610    key: K,
611    timestamp: i64,
612    options: Option<ExpireOptions>,
613  ) -> impl Future<Output = FredResult<R>> + Send
614  where
615    R: FromValue,
616    K: Into<Key> + Send,
617  {
618    async move {
619      into!(key);
620      commands::keys::pexpire_at(self, key, timestamp, options)
621        .await?
622        .convert()
623    }
624  }
625
626  /// PEXPIRETIME has the same semantic as EXPIRETIME, but returns the absolute Unix expiration timestamp in
627  /// milliseconds instead of seconds.
628  ///
629  /// <https://redis.io/docs/latest/commands/pexpiretime/>
630  fn pexpire_time<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
631  where
632    R: FromValue,
633    K: Into<Key> + Send,
634  {
635    async move {
636      into!(key);
637      commands::keys::pexpire_time(self, key).await?.convert()
638    }
639  }
640
641  /// Returns number of keys that exist from the `keys` arguments.
642  ///
643  /// <https://redis.io/commands/exists>
644  fn exists<R, K>(&self, keys: K) -> impl Future<Output = FredResult<R>> + Send
645  where
646    R: FromValue,
647    K: Into<MultipleKeys> + Send,
648  {
649    async move {
650      into!(keys);
651      commands::keys::exists(self, keys).await?.convert()
652    }
653  }
654
655  /// Runs the longest common subsequence algorithm on two keys.
656  ///
657  /// <https://redis.io/commands/lcs/>
658  fn lcs<R, K1, K2>(
659    &self,
660    key1: K1,
661    key2: K2,
662    len: bool,
663    idx: bool,
664    minmatchlen: Option<i64>,
665    withmatchlen: bool,
666  ) -> impl Future<Output = Result<R, Error>> + Send
667  where
668    R: FromValue,
669    K1: Into<Key> + Send,
670    K2: Into<Key> + Send,
671  {
672    async move {
673      into!(key1, key2);
674      commands::keys::lcs(self, key1, key2, len, idx, minmatchlen, withmatchlen)
675        .await?
676        .convert()
677    }
678  }
679
680  /// Fetch one page of `SCAN` results with the provided cursor.
681  ///
682  /// With a clustered the deployment the caller must include a hash tag in the pattern or manually specify the server
683  /// via [with_cluster_node](crate::clients::Client::with_cluster_node) or
684  /// [with_options](crate::clients::Client::with_options).
685  fn scan_page<R, S, P>(
686    &self,
687    cursor: S,
688    pattern: P,
689    count: Option<u32>,
690    r#type: Option<ScanType>,
691  ) -> impl Future<Output = FredResult<R>> + Send
692  where
693    R: FromValue,
694    S: Into<Str> + Send,
695    P: Into<Str> + Send,
696  {
697    async move {
698      into!(cursor, pattern);
699      commands::scan::scan_page(self, cursor, pattern, count, r#type, None, None)
700        .await?
701        .convert()
702    }
703  }
704}