dtypes/redis/rwlock/
writer.rs

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