59 lines
1.6 KiB
Rust
59 lines
1.6 KiB
Rust
use deadpool_redis::cluster::Pool as RedisPool;
|
|
pub async fn acquire_repo_lock(
|
|
pool: &RedisPool,
|
|
repo_id: uuid::Uuid,
|
|
lock_value: &str,
|
|
ttl_secs: usize,
|
|
) -> redis::RedisResult<bool> {
|
|
let lock_key = format!("git:repo:lock:{}", repo_id);
|
|
let redis = pool.get().await.map_err(|e| {
|
|
redis::RedisError::from((
|
|
redis::ErrorKind::Io,
|
|
"failed to get Redis connection",
|
|
e.to_string(),
|
|
))
|
|
})?;
|
|
let mut conn: deadpool_redis::cluster::Connection = redis;
|
|
let acquired: Option<String> = redis::cmd("SET")
|
|
.arg(&lock_key)
|
|
.arg(lock_value)
|
|
.arg("NX")
|
|
.arg("EX")
|
|
.arg(ttl_secs)
|
|
.query_async(&mut conn)
|
|
.await?;
|
|
Ok(acquired.is_some())
|
|
}
|
|
pub async fn release_repo_lock(
|
|
pool: &RedisPool,
|
|
repo_id: uuid::Uuid,
|
|
lock_value: &str,
|
|
) {
|
|
let lock_key = format!("git:repo:lock:{}", repo_id);
|
|
let redis = match pool.get().await {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
tracing::warn!(error = %e, repo_id = %repo_id, "lock_release_redis_connection_failed");
|
|
return;
|
|
}
|
|
};
|
|
let mut conn: deadpool_redis::cluster::Connection = redis;
|
|
let script = redis::Script::new(
|
|
r#"
|
|
if redis.call("GET", KEYS[1]) == ARGV[1] then
|
|
redis.call("DEL", KEYS[1])
|
|
return 1
|
|
end
|
|
return 0
|
|
"#,
|
|
);
|
|
if let Err(e) = script
|
|
.key(&lock_key)
|
|
.arg(lock_value)
|
|
.invoke_async::<i32>(&mut conn)
|
|
.await
|
|
{
|
|
tracing::warn!(error = %e, repo_id = %repo_id, "lock_release_failed");
|
|
}
|
|
}
|