refactor(redis_interface): return MsetnxReply from MSETNX wrapper (#170)

This commit is contained in:
Sanchith Hegde
2022-12-19 16:25:24 +05:30
committed by GitHub
parent 1cdc1367a7
commit 4edc97e57e
4 changed files with 35 additions and 19 deletions

View File

@ -24,7 +24,7 @@ use router_env::{tracing, tracing::instrument};
use crate::{ use crate::{
errors, errors,
types::{HsetnxReply, RedisEntryId, SetnxReply}, types::{HsetnxReply, MsetnxReply, RedisEntryId, SetnxReply},
}; };
impl super::RedisConnectionPool { impl super::RedisConnectionPool {
@ -47,13 +47,16 @@ impl super::RedisConnectionPool {
.change_context(errors::RedisError::SetFailed) .change_context(errors::RedisError::SetFailed)
} }
pub async fn msetnx<V>(&self, value: V) -> CustomResult<u8, errors::RedisError> pub async fn set_multiple_keys_if_not_exist<V>(
&self,
value: V,
) -> CustomResult<MsetnxReply, errors::RedisError>
where where
V: TryInto<RedisMap> + Debug, V: TryInto<RedisMap> + Debug,
V::Error: Into<fred::error::RedisError>, V::Error: Into<fred::error::RedisError>,
{ {
self.pool self.pool
.msetnx::<u8, V>(value) .msetnx(value)
.await .await
.into_report() .into_report()
.change_context(errors::RedisError::SetFailed) .change_context(errors::RedisError::SetFailed)

View File

@ -21,7 +21,6 @@ pub mod commands;
pub mod errors; pub mod errors;
pub mod types; pub mod types;
pub use fred::prelude::*;
use router_env::logger; use router_env::logger;
pub use self::{commands::*, types::*}; pub use self::{commands::*, types::*};

View File

@ -123,3 +123,22 @@ impl fred::types::FromRedis for HsetnxReply {
} }
} }
} }
#[derive(Eq, PartialEq)]
pub enum MsetnxReply {
KeysSet,
KeysNotSet, // At least one existing key
}
impl fred::types::FromRedis for MsetnxReply {
fn from_value(value: fred::types::RedisValue) -> Result<Self, fred::error::RedisError> {
match value {
fred::types::RedisValue::Integer(1) => Ok(Self::KeysSet),
fred::types::RedisValue::Integer(0) => Ok(Self::KeysNotSet),
_ => Err(fred::error::RedisError::new(
fred::error::RedisErrorKind::Unknown,
"Unexpected MSETNX command reply",
)),
}
}
}

View File

@ -23,8 +23,8 @@ pub trait EphemeralKeyInterface {
mod storage { mod storage {
use common_utils::{date_time, ext_traits::StringExt}; use common_utils::{date_time, ext_traits::StringExt};
use error_stack::{IntoReport, ResultExt}; use error_stack::ResultExt;
use redis_interface::RedisValue; use redis_interface::MsetnxReply;
use time::ext::NumericalDuration; use time::ext::NumericalDuration;
use super::EphemeralKeyInterface; use super::EphemeralKeyInterface;
@ -55,20 +55,21 @@ mod storage {
merchant_id: new.merchant_id, merchant_id: new.merchant_id,
secret: new.secret, secret: new.secret,
}; };
let redis_value = &utils::Encode::<EphemeralKey>::encode_to_string_of_json(&created_ek) let redis_value = utils::Encode::<EphemeralKey>::encode_to_string_of_json(&created_ek)
.change_context(errors::StorageError::KVError) .change_context(errors::StorageError::KVError)
.attach_printable("Unable to serialize ephemeral key")?; .attach_printable("Unable to serialize ephemeral key")?;
let redis_map: Vec<(&str, RedisValue)> = vec![ let redis_map = vec![(&secret_key, &redis_value), (&id_key, &redis_value)];
(&secret_key, redis_value.into()),
(&id_key, redis_value.into()),
];
match self match self
.redis_conn .redis_conn
.msetnx::<Vec<(&str, RedisValue)>>(redis_map) .set_multiple_keys_if_not_exist(redis_map)
.await .await
{ {
Ok(1) => { Ok(MsetnxReply::KeysNotSet) => Err(errors::StorageError::DuplicateValue(
"Ephemeral key already exists".to_string(),
)
.into()),
Ok(MsetnxReply::KeysSet) => {
let expire_at = expires.assume_utc().unix_timestamp(); let expire_at = expires.assume_utc().unix_timestamp();
self.redis_conn self.redis_conn
.set_expire_at(&secret_key, expire_at) .set_expire_at(&secret_key, expire_at)
@ -80,12 +81,6 @@ mod storage {
.change_context(errors::StorageError::KVError)?; .change_context(errors::StorageError::KVError)?;
Ok(created_ek) Ok(created_ek)
} }
Ok(0) => {
Err(errors::StorageError::DuplicateValue("ephimeral_key".to_string()).into())
}
Ok(i) => Err(errors::StorageError::KVError)
.into_report()
.attach_printable_lazy(|| format!("Invalid response for HSETNX: {i}")),
Err(er) => Err(er).change_context(errors::StorageError::KVError), Err(er) => Err(er).change_context(errors::StorageError::KVError),
} }
} }