1use once_cell::sync::Lazy;
2use redis::Script;
3use std::time::SystemTime;
4
5static LOCK_SCRIPT: Lazy<Script> =
6 Lazy::new(|| Script::new(include_str!("./redis_scripts/batches_lock.lua")));
7
8pub async fn lock(
9 key: &str,
10 field: &str,
11 lock_milli_second: u128,
12 redis_conn: &mut redis::aio::Connection,
13) -> Result<bool, redis::RedisError> {
14 let start_utsms = SystemTime::now()
15 .duration_since(SystemTime::UNIX_EPOCH)
16 .unwrap()
17 .as_millis();
18 let mut invocation = LOCK_SCRIPT.key(key);
19 invocation.key(field);
20 invocation.arg(start_utsms.to_string());
21 invocation.arg(lock_milli_second.to_string());
22 let res: Option<String> = invocation.invoke_async(redis_conn).await?;
23 Ok(res.is_some())
24}
25
26#[cfg(test)]
27mod tests {
28 use crate::lock;
29
30 #[tokio::test]
31 async fn it_works() {
32 let client = redis::Client::open("redis://127.0.0.1/").unwrap();
33 let mut con = client.get_async_connection().await.unwrap();
34 let res1 = lock("mutex", "test", 1000, &mut con).await.unwrap();
35 assert_eq!(true, res1);
36 let res2 = lock("mutex", "test", 1000, &mut con).await.unwrap();
37 assert_eq!(false, res2);
38 tokio::time::sleep(tokio::time::Duration::from_millis(1001)).await;
39 let res3 = lock("mutex", "test", 1000, &mut con).await.unwrap();
40 assert_eq!(true, res3);
41 tokio::time::sleep(tokio::time::Duration::from_millis(1001)).await;
42 }
43}