mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
refactor(redis_interface): return MsetnxReply from MSETNX wrapper (#170)
This commit is contained in:
@ -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)
|
||||||
|
|||||||
@ -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::*};
|
||||||
|
|||||||
@ -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",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user