dtypes/redis/rwlock/
reader.rs

1use super::lock::RwLock;
2use crate::redis::rwlock::constants::{LOAD_SCRIPT, READER_LOCK_DROP};
3use crate::redis::types::Generic;
4use serde::de::DeserializeOwned;
5use serde::Serialize;
6use std::ops::Deref;
7
8pub struct RwLockReadGuard<'a, T> {
9    lock: &'a RwLock<T>,
10    uuid: usize,
11    conn: redis::Connection,
12    cache: Option<T>,
13}
14
15impl<'a, T> RwLockReadGuard<'a, T>
16where
17    T: Serialize + DeserializeOwned,
18{
19    pub(crate) fn new(lock: &'a RwLock<T>, uuid: usize, conn: redis::Connection) -> Self {
20        Self {
21            lock,
22            uuid,
23            conn,
24            cache: None,
25        }
26    }
27
28    /// Loads the value from Redis.
29    /// This function blocks until the value is loaded.
30    /// Shadows the load operation of the guarded value.
31    pub fn acquire(&mut self) -> &T {
32        self.cache = self.try_get();
33        self.cache.as_ref().unwrap()
34    }
35
36    fn try_get(&mut self) -> Option<T> {
37        let script = redis::Script::new(LOAD_SCRIPT);
38        let result: Option<String> = script
39            .arg(&self.lock.data.key)
40            .arg(self.uuid)
41            .invoke(&mut self.conn)
42            .expect("Failed to load value. You should not see this!");
43        let result = result?;
44
45        if result == "nil" {
46            return None;
47        }
48        Some(serde_json::from_str(&result).expect("Failed to deserialize value"))
49    }
50}
51
52impl<'a, T> Deref for RwLockReadGuard<'a, T> {
53    type Target = Generic<T>;
54
55    fn deref(&self) -> &Self::Target {
56        &self.lock.data
57    }
58}
59
60impl<T> Drop for RwLockReadGuard<'_, T> {
61    fn drop(&mut self) {
62        let mut conn = self.client.get_connection().unwrap();
63        let _: () = redis::Script::new(READER_LOCK_DROP)
64            .arg(&self.lock.data.key)
65            .arg(self.uuid)
66            .invoke(&mut conn)
67            .unwrap();
68    }
69}