Skip to main content

nexus_common/db/kv/
traits.rs

1use super::index::*;
2use crate::types::DynError;
3use async_trait::async_trait;
4use json::JsonAction;
5use serde::{de::DeserializeOwned, Serialize};
6use sorted_sets::{ScoreAction, SortOrder, SORTED_PREFIX};
7
8/// A trait for operations involving Redis storage. Implement this trait for types that need to be stored
9/// and retrieved from Redis with serialization and deserialization capabilities.
10#[async_trait]
11pub trait RedisOps: Serialize + DeserializeOwned + Send + Sync {
12    /// Provides a prefix string for the Redis key.
13    ///
14    /// This method should return a prefix string that helps namespace the keys in Redis,
15    /// preventing key collisions. The prefix is typically derived from the struct name.
16    ///
17    /// # Returns
18    ///
19    /// A `String` representing the prefix for Redis keys.
20    async fn prefix() -> String {
21        let type_name = std::any::type_name::<Self>();
22        let struct_name = type_name.split("::").last().unwrap_or_default();
23
24        // Insert ":" before each uppercase letter except the first one
25        let mut prefixed_name = String::new();
26        let chars = struct_name.chars().peekable();
27
28        for c in chars {
29            if c.is_uppercase() && !prefixed_name.is_empty() {
30                prefixed_name.push(':');
31            }
32            prefixed_name.push(c);
33        }
34
35        prefixed_name
36    }
37
38    // ############################################################
39    // ################# JSON related functions ###################
40    // ############################################################
41
42    /// Sets the data in Redis using the provided key parts.
43    ///
44    /// This method serializes the data and stores it in Redis under the key generated
45    /// from the provided `key_parts`. It can also set an expiration time for the key if required.
46    ///
47    /// # Arguments
48    ///
49    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the value is stored
50    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
51    /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
52    ///
53    /// # Errors
54    ///
55    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
56    async fn put_index_json(
57        &self,
58        key_parts: &[&str],
59        prefix: Option<String>,
60        expiration: Option<i64>,
61    ) -> Result<(), DynError> {
62        let prefix = prefix.unwrap_or(Self::prefix().await);
63        json::put(&prefix, &key_parts.join(":"), self, None, expiration).await
64    }
65
66    /// Retrieves data from Redis using the provided key parts.
67    ///
68    /// This method deserializes the data stored under the key generated from the provided `key_parts` in Redis.
69    /// If the key is not found, it returns `None`.
70    ///
71    /// # Arguments
72    ///
73    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the value is stored.
74    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
75    ///
76    /// # Returns
77    ///
78    /// An `Option<Self>` containing the deserialized data if found, or `None` if the key does not exist.
79    ///
80    /// # Errors
81    ///
82    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
83    async fn try_from_index_json(
84        key_parts: &[&str],
85        prefix: Option<String>,
86    ) -> Result<Option<Self>, DynError> {
87        let prefix = prefix.unwrap_or(Self::prefix().await);
88        json::get(&prefix, &key_parts.join(":"), None).await
89    }
90
91    /// Retrieves multiple JSON objects from Redis using the provided key parts.
92    ///
93    /// This method deserializes the data stored under the keys generated from the provided `key_parts_list` in Redis.
94    /// It returns a vector of options, where each option corresponds to the existence of the key in Redis.
95    ///
96    /// # Arguments
97    ///
98    /// * `key_parts_list` - A slice of slices, where each inner slice contains string slices representing
99    ///   the parts used to form the key under which the corresponding value is stored.
100    ///
101    /// # Returns
102    ///
103    /// A `Vec<Option<Self>>` containing the deserialized data if found, or `None` if a key does not exist.
104    async fn try_from_index_multiple_json(
105        key_parts_list: &[&[&str]],
106    ) -> Result<Vec<Option<Self>>, DynError> {
107        let prefix = Self::prefix().await;
108        let keys: Vec<String> = key_parts_list
109            .iter()
110            .map(|key_parts| key_parts.join(":"))
111            .collect();
112
113        json::get_multiple(&prefix, &keys, None).await
114    }
115
116    /// Stores multiple key-value pairs in Redis, where each key is constructed from the provided key parts
117    /// and each value is an item from the given collection.
118    ///
119    /// This method serializes each item in the collection and stores it in Redis under keys generated
120    /// by joining the elements of the corresponding slices in `key_parts_list`. It efficiently handles
121    /// the setting of multiple key-value pairs in a single operation.
122    ///
123    /// # Arguments
124    ///
125    /// * `key_parts_list` - A slice of slices, where each inner slice is a list of string slices representing
126    ///   the components used to generate the Redis key for the corresponding value in the `collection`.
127    ///   Each slice in this list must align with the corresponding index in `collection`.
128    ///
129    /// * `collection` - A vector of `Option<Self>` representing the values to be stored in Redis. Each value is serialized
130    ///   before being stored, and the vector should be of the same length as `key_parts_list`.
131    ///
132    /// # Returns
133    ///
134    /// This function returns a `Result` indicating success or failure. A successful result means that
135    /// all key-value pairs were successfully stored in Redis.
136    async fn put_multiple_json_indexes(
137        key_parts_list: &[&[&str]],
138        collection: Vec<Option<Self>>,
139    ) -> Result<(), DynError> // The items in the collection must be serializable
140    {
141        let mut data = Vec::with_capacity(key_parts_list.len());
142        for (i, key_parts) in key_parts_list.iter().enumerate() {
143            let key = key_parts.join(":");
144            data.push((key, &collection[i]));
145        }
146
147        json::put_multiple(&Self::prefix().await, &data).await
148    }
149
150    /// Removes multiple JSON objects from Redis using the provided key parts.
151    ///
152    /// This method deletes the data stored under the keys generated from the provided `key_parts_list` in Redis.
153    /// It returns a result indicating success or failure.
154    ///
155    /// # Arguments
156    ///
157    /// * `key_parts_list` - A slice of slices, where each inner slice contains string slices representing
158    ///   the parts used to form the key under which the corresponding value is stored.
159    ///
160    /// # Returns
161    ///
162    /// A `Result` indicating success or failure. If successful, all keys are removed from Redis.
163    ///
164    /// # Errors
165    ///
166    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
167    async fn remove_from_index_multiple_json(key_parts_list: &[&[&str]]) -> Result<(), DynError> {
168        let prefix = Self::prefix().await;
169        let keys: Vec<String> = key_parts_list
170            .iter()
171            .map(|key_parts| key_parts.join(":"))
172            .collect();
173
174        json::del_multiple(&prefix, &keys).await
175    }
176
177    /// Modifies a numeric field in a Redis JSON object by either incrementing or decrementing it.
178    ///
179    /// This method performs an operation on a numeric field in Redis JSON at the given path,
180    /// either incrementing or decrementing it based on the `JsonAction` provided.
181    ///
182    /// # Arguments
183    ///
184    /// * `key_parts` - A slice of string slices representing the parts used to form the key under which the JSON object is stored.
185    /// * `field` - A string slice representing the field to be modified in the JSON object.
186    /// * `action` - A `JsonAction` enum that specifies whether to increment or decrement the field.
187    ///
188    /// # Returns
189    ///
190    /// Returns a result indicating success or failure.
191    ///
192    /// # Errors
193    ///
194    /// Returns an error if the operation fails, such as if the Redis connection is unavailable or the field is not numeric.
195    async fn modify_json_field(
196        key_parts: &[&str],
197        field: &str,
198        action: JsonAction,
199    ) -> Result<(), DynError> {
200        let prefix = Self::prefix().await;
201        let key = key_parts.join(":");
202        json::modify_json_field(&prefix, &key, field, action, None).await
203    }
204
205    // ############################################################
206    // ################# List related functions ###################
207    // ############################################################
208
209    /// Adds elements to a Redis list using the provided key parts.
210    ///
211    /// This method serializes the data and appends it to a Redis list under the key generated
212    /// from the provided `key_parts`.
213    ///
214    /// # Arguments
215    ///
216    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the list is stored.
217    ///
218    /// # Errors
219    ///
220    /// Returns an error if the operation fails, such as if the Redis connection is unavailable or
221    /// if there is an issue with serialization.
222    async fn put_index_list<T>(&self, key_parts: &[&str]) -> Result<(), DynError>
223    where
224        Self: AsRef<[T]>,            // Self can be dereferenced into a slice of T
225        T: AsRef<str> + Send + Sync, // The items must be convertible to &str
226    {
227        let prefix = Self::prefix().await;
228        let key = key_parts.join(":");
229
230        // TODO: Unsafe. If re-indexed it will duplicate follower/following list entries.
231        // Need reading, matching out the duplicates then storing. Inneficient.
232        // Needs mode safety for double-write.
233
234        // Directly use the string representations of items without additional serialization
235        let collection = self.as_ref();
236        let values: Vec<&str> = collection.iter().map(|item| item.as_ref()).collect();
237
238        // Store the values in the Redis list
239        lists::put(&prefix, &key, &values).await
240    }
241
242    /// Retrieves a range of elements from a Redis list using the provided key parts.
243    ///
244    /// This method fetches elements from a Redis list stored under the key generated from the provided `key_parts`.
245    /// The range is defined by `skip` and `limit` parameters.
246    ///
247    /// # Arguments
248    ///
249    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the list is stored.
250    /// * `skip` - An optional number of elements to skip (useful for pagination).
251    /// * `limit` - An optional number of elements to return (useful for pagination).
252    ///
253    /// # Returns
254    ///
255    /// Returns a vector of deserialized elements if they exist, or an empty vector if no matching elements are found.
256    ///
257    /// # Errors
258    ///
259    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
260    async fn try_from_index_list(
261        key_parts: &[&str],
262        skip: Option<usize>,
263        limit: Option<usize>,
264    ) -> Result<Option<Vec<String>>, DynError> {
265        let prefix = Self::prefix().await;
266        let key = key_parts.join(":");
267        lists::get_range(&prefix, &key, skip, limit).await
268    }
269
270    // ############################################################
271    // ################# SET related functions ###################
272    // ############################################################
273
274    /// Adds elements to a Redis set using the provided key parts.
275    ///
276    /// This method adds elements to a Redis set under the key generated from the provided `key_parts`.
277    /// It ensures that each element in the set is unique.
278    ///
279    /// # Arguments
280    ///
281    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
282    /// * `values` - A list of string that represents the value to add in the index
283    /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
284    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
285    /// # Errors
286    ///
287    /// Returns an error if the operation fails, such as if the Redis connection is unavailable or
288    /// if there is an issue with serialization.
289    async fn put_index_set(
290        key_parts: &[&str],
291        values: &[&str],
292        expiration: Option<i64>,
293        prefix: Option<String>,
294    ) -> Result<(), DynError> {
295        let prefix = prefix.unwrap_or(Self::prefix().await);
296        let key = key_parts.join(":");
297        // Store the values in the Redis set
298        sets::put(&prefix, &key, values, expiration).await
299    }
300
301    /// Removes elements from a Redis set using the provided key parts.
302    ///
303    /// This method removes elements from a Redis set stored under the key generated from the provided `key_parts`.
304    ///
305    /// # Arguments
306    ///
307    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
308    /// * `values` - A slice of string slices representing the elements to be removed from the set.
309    ///
310    /// # Errors
311    ///
312    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
313    async fn remove_from_index_set<T>(&self, key_parts: &[&str]) -> Result<(), DynError>
314    where
315        Self: AsRef<[T]>,            // Self can be dereferenced into a slice of T
316        T: AsRef<str> + Send + Sync, // The items must be convertible to &str
317    {
318        let prefix = Self::prefix().await;
319        let key = key_parts.join(":");
320
321        // Directly use the string representations of items without additional serialization
322        let collection = self.as_ref();
323        let values: Vec<&str> = collection.iter().map(|item| item.as_ref()).collect();
324
325        // Remove the values from the Redis set
326        sets::del(&prefix, &key, &values).await
327    }
328
329    /// Retrieves a range of elements from a Redis set using the provided key parts.
330    ///
331    /// This method fetches elements from a Redis set stored under the key generated from the provided `key_parts`.
332    /// The range is defined by `skip` and `limit` parameters.
333    ///
334    /// # Arguments
335    ///
336    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
337    /// * `skip` - An optional number of elements to skip (useful for pagination).
338    /// * `limit` - An optional number of elements to return (useful for pagination).
339    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
340    /// # Returns
341    ///
342    /// Returns a vector of deserialized elements if they exist, or an empty vector if no matching elements are found.
343    ///
344    /// # Errors
345    ///
346    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
347    async fn try_from_index_set(
348        key_parts: &[&str],
349        skip: Option<usize>,
350        limit: Option<usize>,
351        prefix: Option<String>,
352    ) -> Result<Option<Vec<String>>, DynError> {
353        let combined_prefix = match prefix {
354            Some(p) => format!("{}:{}", p, Self::prefix().await),
355            None => Self::prefix().await,
356        };
357        let key = key_parts.join(":");
358        sets::get_range(&combined_prefix, &key, skip, limit).await
359    }
360
361    /// Checks if a member exists in a Redis set and if the set exists using the provided key parts.
362    ///
363    /// This method checks if a specific member is present in the Redis set stored under the key
364    /// generated from the provided `key_parts`. It also determines if the set itself exists.
365    ///
366    /// # Arguments
367    ///
368    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
369    /// * `member` - A string slice representing the member to check for existence in the set.
370    ///
371    /// # Returns
372    ///
373    /// Returns `Ok((true, true))` if the set exists and the member is in the set,
374    /// `Ok((true, false))` if the set exists but the member is not in the set,
375    /// `Ok((false, false))` if the set does not exist.
376    ///
377    /// # Errors
378    ///
379    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
380    async fn check_set_member(key_parts: &[&str], member: &str) -> Result<(bool, bool), DynError> {
381        let prefix = Self::prefix().await;
382        let key = key_parts.join(":");
383        sets::check_member(&prefix, &key, member).await
384    }
385
386    /// Retrieves the size of a Redis set using the provided key parts.
387    ///
388    /// This method retrieves the number of elements in a Redis set stored under the key generated from the provided `key_parts`.
389    /// It returns `Ok(Some(size))` if the set exists, or `Ok(None)` if the set does not exist.
390    ///
391    /// # Arguments
392    ///
393    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the set is stored.
394    ///
395    /// # Returns
396    ///
397    /// Returns `Ok(Some(size))` where `size` is the number of elements in the set, or `Ok(None)` if the set does not exist.
398    ///
399    /// # Errors
400    ///
401    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
402    async fn get_set_size(key_parts: &[&str]) -> Result<Option<usize>, DynError> {
403        let prefix = Self::prefix().await;
404        let key = key_parts.join(":");
405        sets::get_size(&prefix, &key).await
406    }
407
408    /// Fetches multiple sets from Redis using the specified key components.
409    ///
410    /// # Arguments
411    /// * `key_parts_list` - A slice of string slices, where each inner slice represents the components
412    ///   used to construct the Redis keys.
413    /// * `prefix` - An optional string representing the prefix for the Redis keys
414    /// * `member` - An optional string reference representing a specific element to check for member in each SET
415    /// * `limit` - An optional parameter specifying the maximum number of elements to fetch from each SET
416    ///   If `None`, all elements will be retrieved.
417    async fn try_from_multiple_sets(
418        key_parts_list: &[&str],
419        prefix: Option<String>,
420        member: Option<&str>,
421        limit: Option<usize>,
422    ) -> Result<Vec<Option<(Vec<String>, usize, bool)>>, DynError> {
423        let combined_prefix = match prefix {
424            Some(p) => format!("{}:{}", p, Self::prefix().await),
425            None => Self::prefix().await,
426        };
427        sets::get_multiple_sets(&combined_prefix, key_parts_list, member, limit).await
428    }
429
430    /// Adds elements to multiple Redis sets using the provided keys and collections.
431    ///
432    /// This asynchronous function allows you to add elements to multiple Redis sets,
433    /// with each set identified by a key generated from the `common_key` and `index_ref`.
434    /// The function ensures that each element in each set is unique.
435    ///
436    /// # Arguments
437    ///
438    /// * `common_key` - A slice of string slices representing the common part of the Redis keys.
439    ///   This will be combined with each element in `index` to generate the full Redis key.
440    /// * `index` - A slice of string slices representing the unique identifiers to append to the `common_key` to form the full Redis keys.
441    /// * `collections_refs` - A slice of vectors, where each inner vector contains elements to be added to the corresponding Redis set
442    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
443    /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
444    ///
445    /// # Returns
446    ///
447    /// This function returns a `Result` indicating success or failure. A successful result means that
448    /// all elements were successfully added to their respective Redis sets.
449    ///
450    /// # Errors
451    ///
452    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
453    async fn put_multiple_set_indexes(
454        common_key: &[&str],
455        index: &[&str],
456        collections_refs: &[Vec<&str>],
457        prefix: Option<String>,
458        expiration: Option<i64>,
459    ) -> Result<(), DynError> {
460        // Ensure the lengths of keys_refs and collections_refs match
461        if index.len() != collections_refs.len() {
462            // TODO: Maybe create redis related errors
463            return Err("Keys refs and collections refs length mismatch".into());
464        }
465        let combined_prefix = match prefix {
466            Some(p) => format!("{}:{}", p, Self::prefix().await),
467            None => Self::prefix().await,
468        };
469
470        let refs: Vec<&[&str]> = collections_refs
471            .iter()
472            .map(|inner_vec| inner_vec.as_slice())
473            .collect();
474        let slice: &[&[&str]] = refs.as_slice();
475
476        sets::put_multiple_sets(&combined_prefix, common_key, index, slice, expiration).await
477    }
478
479    /// Retrieves random elements from a Redis set using the provided key parts.
480    ///
481    /// This method fetches random elements from a Redis set stored under the key generated from the provided `key_parts`.
482    /// The number of elements retrieved is defined by the `count` parameter.
483    /// # Arguments
484    ///
485    /// * `key_parts` - Components of the key under which the set is stored.
486    /// * `count` - The number of random elements to retrieve.
487    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
488    ///
489    /// # Returns
490    ///
491    /// Returns `Ok(Some(Vec<String>))` if the set exists and random elements are retrieved.
492    /// Returns `Ok(None)` if the set does not exist.
493    ///
494    /// # Errors
495    ///
496    /// Returns an error if the Redis operation fails.
497    async fn try_get_random_from_index_set(
498        key_parts: &[&str],
499        count: isize,
500        prefix: Option<String>,
501    ) -> Result<Option<Vec<String>>, DynError> {
502        let prefix = prefix.unwrap_or(Self::prefix().await);
503        let key = key_parts.join(":");
504        sets::get_random_members(&prefix, &key, count).await
505    }
506
507    // ############################################################
508    // ########### SORTED SET related functions ###################
509    // ############################################################
510
511    /// Checks if a member exists in a Redis sorted set and retrieves its score if it exists.
512    ///
513    /// This method checks if a specific member is present in the Redis sorted set stored under the key
514    /// generated from the provided `key_parts`. If the member is found, it returns its score.
515    ///
516    /// # Arguments
517    ///
518    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
519    /// * `member` - A slice of string slices that represent the parts used to form the key identifying the member within the sorted set.
520    async fn check_sorted_set_member(
521        prefix: Option<&str>,
522        key_parts: &[&str],
523        member: &[&str],
524    ) -> Result<Option<isize>, DynError> {
525        let prefix = prefix.unwrap_or(SORTED_PREFIX);
526        let key = key_parts.join(":");
527        let member_key = member.join(":");
528        sorted_sets::check_member(prefix, &key, &member_key).await
529    }
530
531    /// Adds elements to a Redis sorted set using the provided key parts.
532    ///
533    /// This method adds elements to a Redis sorted set under the key generated from the provided `key_parts`.
534    /// The elements are associated with scores, which determine their order in the set.
535    ///
536    /// # Arguments
537    ///
538    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
539    /// * `elements` - A slice of tuples where each tuple contains a reference to a string slice representing
540    ///                the element and a f64 representing the score of the element.
541    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
542    /// * `expiration` - An optional `i64` specifying the TTL (in seconds) for the set. If `None`, no TTL will be set.
543    ///
544    /// # Errors
545    ///
546    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
547    async fn put_index_sorted_set(
548        key_parts: &[&str],
549        elements: &[(f64, &str)],
550        prefix: Option<&str>,
551        expiration: Option<i64>,
552    ) -> Result<(), DynError> {
553        let prefix = prefix.unwrap_or(SORTED_PREFIX);
554        let key = key_parts.join(":");
555        // Store the elements in the Redis sorted set
556        sorted_sets::put(prefix, &key, elements, expiration).await
557    }
558
559    /// Updates the score of a member in a Redis sorted set.
560    ///
561    /// This method updates the score associated with a specific member in a Redis sorted set
562    /// identified by the provided key parts. The score can be mutated (incremented, decremented, or set) based on the `score_mutation` parameter.
563    ///
564    /// # Arguments
565    ///
566    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
567    /// * `member` - A slice of string slices that represent the parts used to form the key identifying the member within the sorted set.
568    /// * `score_mutation` - A `ScoreAction` that defines how the score should be modified (e.g., incremented or decremented).
569    async fn put_score_index_sorted_set(
570        key_parts: &[&str],
571        member: &[&str],
572        score_mutation: ScoreAction,
573    ) -> Result<(), DynError> {
574        let key = key_parts.join(":");
575        let member_key = member.join(":");
576        sorted_sets::put_score(SORTED_PREFIX, &key, &member_key, score_mutation).await
577    }
578
579    /// Removes elements from a Redis sorted set using the provided key parts.
580    ///
581    /// This method removes the specified elements from the Redis sorted set identified by the key generated
582    /// from the provided `key_parts`.
583    ///
584    /// # Arguments
585    ///
586    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
587    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
588    /// * `items` - A slice of string slices representing the elements to be removed from the sorted set.
589    ///
590    /// # Errors
591    ///
592    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
593    async fn remove_from_index_sorted_set(
594        prefix: Option<&str>,
595        key_parts: &[&str],
596        items: &[&str],
597    ) -> Result<(), DynError> {
598        if items.is_empty() {
599            return Ok(());
600        }
601
602        let prefix = prefix.unwrap_or(SORTED_PREFIX);
603        // Create the key by joining the key parts
604        let key = key_parts.join(":");
605        // Call the sorted_sets::del function to remove the items from the sorted set
606        sorted_sets::del(prefix, &key, items).await
607    }
608
609    /// Retrieves a range of elements from a Redis sorted set using the provided key parts.
610    ///
611    /// This method fetches elements from a Redis sorted set stored under the key generated from the provided `key_parts`.
612    /// The range is defined by `skip` and `limit` parameters.
613    ///
614    /// # Arguments
615    ///
616    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
617    /// * `start` - An optional value representing the beginning of the stream timeframe or score. If `None`, no lower bound is applied.
618    /// * `end` - An optional value representing the end of the stream timeframe or score. If `None`, no upper bound is applied.
619    /// * `skip` - An optional number of elements to skip (useful for pagination).
620    /// * `limit` - An optional number of elements to return (useful for pagination).
621    /// * `prefix` - An optional string representing the prefix for the Redis keys. If `Some(String)`, the prefix will be used
622    ///
623    /// # Returns
624    ///
625    /// Returns a vector of tuples containing the elements and their scores if they exist, or an empty vector if no matching elements are found.
626    ///
627    /// # Errors
628    ///
629    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
630    async fn try_from_index_sorted_set(
631        key_parts: &[&str],
632        start: Option<f64>,
633        end: Option<f64>,
634        skip: Option<usize>,
635        limit: Option<usize>,
636        sorting: SortOrder,
637        prefix: Option<&str>,
638    ) -> Result<Option<Vec<(String, f64)>>, DynError> {
639        let key = key_parts.join(":");
640        let prefix = prefix.unwrap_or("Sorted");
641
642        sorted_sets::get_range(prefix, &key, end, start, skip, limit, sorting).await
643    }
644
645    /// Retrieves a lexicographical range of elements from a Redis sorted set using the provided key parts.
646    ///
647    /// This method fetches elements from a Redis sorted set stored under the key generated from the provided `key_parts`.
648    /// The range is defined by `min` and `max` lexicographical bounds.
649    ///
650    /// # Arguments
651    ///
652    /// * `key_parts` - A slice of string slices that represent the parts used to form the key under which the sorted set is stored.
653    /// * `min` - The minimum lexicographical bound (inclusive).
654    /// * `max` - The maximum lexicographical bound (exclusive).
655    /// * `skip` - An optional number of elements to skip (useful for pagination).
656    /// * `limit` - An optional number of elements to return (useful for pagination).
657    ///
658    /// # Returns
659    ///
660    /// Returns a vector of elements if they exist, or an empty vector if no matching elements are found.
661    ///
662    /// # Errors
663    ///
664    /// Returns an error if the operation fails, such as if the Redis connection is unavailable.
665    async fn try_from_index_sorted_set_lex(
666        key_parts: &[&str],
667        min: &str,
668        max: &str,
669        skip: Option<usize>,
670        limit: Option<usize>,
671    ) -> Result<Option<Vec<String>>, DynError> {
672        let key = key_parts.join(":");
673        sorted_sets::get_lex_range("Sorted", &key, min, max, skip, limit).await
674    }
675}