diff --git a/src/clients/cache/momento/commands/item_get_type.rs b/src/clients/cache/momento/commands/item_get_type.rs new file mode 100644 index 00000000..f5e07c8e --- /dev/null +++ b/src/clients/cache/momento/commands/item_get_type.rs @@ -0,0 +1,37 @@ +use super::*; +use ::momento::cache::ItemGetTypeResponse; + +pub async fn item_get_type( + client: &mut CacheClient, + config: &Config, + cache_name: &str, + request: workload::client::ItemGetType, +) -> std::result::Result<(), ResponseError> { + ITEM_GET_TYPE.increment(); + + match timeout( + config.client().unwrap().request_timeout(), + client.item_get_type(cache_name, (*request.key).to_owned()), + ) + .await + { + Ok(Ok(r)) => match r { + ItemGetTypeResponse::Hit { .. } => { + ITEM_GET_TYPE_HIT.increment(); + Ok(()) + } + ItemGetTypeResponse::Miss => { + ITEM_GET_TYPE_MISS.increment(); + Ok(()) + } + }, + Ok(Err(e)) => { + ITEM_GET_TYPE_EX.increment(); + Err(e.into()) + } + Err(_) => { + ITEM_GET_TYPE_TIMEOUT.increment(); + Err(ResponseError::Timeout) + } + } +} diff --git a/src/clients/cache/momento/commands/mod.rs b/src/clients/cache/momento/commands/mod.rs index b6897224..b7be257d 100644 --- a/src/clients/cache/momento/commands/mod.rs +++ b/src/clients/cache/momento/commands/mod.rs @@ -9,6 +9,7 @@ mod hash_get; mod hash_get_all; mod hash_increment; mod hash_set; +mod item_get_type; mod list_fetch; mod list_length; mod list_pop_back; @@ -18,6 +19,8 @@ mod list_push_front; mod list_remove; mod set; mod set_add; +mod set_if_absent; +mod set_if_present_and_not_equal; mod set_members; mod set_remove; mod sorted_set_add; @@ -34,6 +37,7 @@ pub use hash_get::*; pub use hash_get_all::*; pub use hash_increment::*; pub use hash_set::*; +pub use item_get_type::*; pub use list_fetch::*; pub use list_length::*; pub use list_pop_back::*; @@ -43,6 +47,8 @@ pub use list_push_front::*; pub use list_remove::*; pub use set::*; pub use set_add::*; +pub use set_if_absent::*; +pub use set_if_present_and_not_equal::*; pub use set_members::*; pub use set_remove::*; pub use sorted_set_add::*; diff --git a/src/clients/cache/momento/commands/set_if_absent.rs b/src/clients/cache/momento/commands/set_if_absent.rs new file mode 100644 index 00000000..4e63b506 --- /dev/null +++ b/src/clients/cache/momento/commands/set_if_absent.rs @@ -0,0 +1,41 @@ +use super::*; +use ::momento::cache::SetIfAbsentResponse; + +pub async fn set_if_absent( + client: &mut CacheClient, + config: &Config, + cache_name: &str, + request: workload::client::SetIfAbsent, +) -> std::result::Result<(), ResponseError> { + SET_IF_ABSENT.increment(); + + match timeout( + config.client().unwrap().request_timeout(), + client.set_if_absent( + cache_name, + (*request.key).to_owned(), + (*request.value).to_owned(), + ), + ) + .await + { + Ok(Ok(r)) => match r { + SetIfAbsentResponse::Stored { .. } => { + SET_IF_ABSENT_STORED.increment(); + Ok(()) + } + SetIfAbsentResponse::NotStored => { + SET_IF_ABSENT_NOT_STORED.increment(); + Ok(()) + } + }, + Ok(Err(e)) => { + SET_IF_ABSENT_EX.increment(); + Err(e.into()) + } + Err(_) => { + SET_IF_ABSENT_TIMEOUT.increment(); + Err(ResponseError::Timeout) + } + } +} diff --git a/src/clients/cache/momento/commands/set_if_present_and_not_equal.rs b/src/clients/cache/momento/commands/set_if_present_and_not_equal.rs new file mode 100644 index 00000000..c9cd7db5 --- /dev/null +++ b/src/clients/cache/momento/commands/set_if_present_and_not_equal.rs @@ -0,0 +1,42 @@ +use super::*; +use ::momento::cache::SetIfPresentAndNotEqualResponse; + +pub async fn set_if_present_and_not_equal( + client: &mut CacheClient, + config: &Config, + cache_name: &str, + request: workload::client::SetIfPresentAndNotEqual, +) -> std::result::Result<(), ResponseError> { + SET_IF_PRESENT_AND_NOT_EQUAL.increment(); + + match timeout( + config.client().unwrap().request_timeout(), + client.set_if_present_and_not_equal( + cache_name, + (*request.key).to_owned(), + (*request.new_value).to_owned(), + (*request.old_value).to_owned(), + ), + ) + .await + { + Ok(Ok(r)) => match r { + SetIfPresentAndNotEqualResponse::Stored { .. } => { + SET_IF_PRESENT_AND_NOT_EQUAL_STORED.increment(); + Ok(()) + } + SetIfPresentAndNotEqualResponse::NotStored => { + SET_IF_PRESENT_AND_NOT_EQUAL_NOT_STORED.increment(); + Ok(()) + } + }, + Ok(Err(e)) => { + SET_IF_PRESENT_AND_NOT_EQUAL_EX.increment(); + Err(e.into()) + } + Err(_) => { + SET_IF_PRESENT_AND_NOT_EQUAL_TIMEOUT.increment(); + Err(ResponseError::Timeout) + } + } +} diff --git a/src/clients/cache/momento/mod.rs b/src/clients/cache/momento/mod.rs index 82e8e563..1786f136 100644 --- a/src/clients/cache/momento/mod.rs +++ b/src/clients/cache/momento/mod.rs @@ -86,6 +86,15 @@ async fn task( ClientRequest::Get(r) => get(&mut client, &config, cache_name, r).await, ClientRequest::Set(r) => set(&mut client, &config, cache_name, r).await, ClientRequest::Delete(r) => delete(&mut client, &config, cache_name, r).await, + ClientRequest::SetIfAbsent(r) => { + set_if_absent(&mut client, &config, cache_name, r).await + } + ClientRequest::SetIfPresentAndNotEqual(r) => { + set_if_present_and_not_equal(&mut client, &config, cache_name, r).await + } + ClientRequest::ItemGetType(r) => { + item_get_type(&mut client, &config, cache_name, r).await + } /* * HASHES (DICTIONARIES) diff --git a/src/config/workload.rs b/src/config/workload.rs index f6174eba..cf6ba195 100644 --- a/src/config/workload.rs +++ b/src/config/workload.rs @@ -427,6 +427,20 @@ pub enum Verb { /// * Momento: unsupported /// * RESP: `SET` with `XX` option Replace, + /// Set the value for a key only if it does not exists. + /// * Momento: `set_if_absent` + /// * RESP: `SET` with `XX` option + SetIfAbsent, + /// Set the value for a key only if it already exists and the + /// current value does not match the value to compare against + /// from the request + /// * Momento: `set_if_present_and_not_equal` + /// * RESP: Raw `SET` with cached value comparison + SetIfPresentAndNotEqual, + /// Get the type of the value stored under the key. + /// * Momento: `item_get_type` + /// * RESP: `TYPE` + ItemGetType, /* * HASHES (DICTIONARIES) diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index be242deb..70b9e080 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -308,7 +308,7 @@ macro_rules! request { paste! { #[allow(dead_code)] pub static [<$ident _EX_COUNTER>]: &'static str = concat!($name, "/exception"); - } + } } paste! { @@ -524,6 +524,24 @@ counter!( "delete requests that resulted in timeout" ); +request!(SET_IF_ABSENT, "set_if_absent"); +counter!(SET_IF_ABSENT_STORED, "set_if_absent/stored"); +counter!(SET_IF_ABSENT_NOT_STORED, "set_if_absent/not_stored"); + +request!(SET_IF_PRESENT_AND_NOT_EQUAL, "set_if_present_and_not_equal"); +counter!( + SET_IF_PRESENT_AND_NOT_EQUAL_STORED, + "set_if_present_and_not_equal/stored" +); +counter!( + SET_IF_PRESENT_AND_NOT_EQUAL_NOT_STORED, + "set_if_present_and_not_equal/not_stored" +); + +request!(ITEM_GET_TYPE, "item_get_type"); +counter!(ITEM_GET_TYPE_HIT, "item_get_type/hit"); +counter!(ITEM_GET_TYPE_MISS, "item_get_type/miss"); + request!(HASH_GET, "hash_get"); counter!(HASH_GET_FIELD_HIT, "hash_get/field_hit"); counter!(HASH_GET_FIELD_MISS, "hash_get/field_miss"); diff --git a/src/workload/client.rs b/src/workload/client.rs index a4440023..feb6d3d5 100644 --- a/src/workload/client.rs +++ b/src/workload/client.rs @@ -42,6 +42,24 @@ pub struct Set { pub ttl: Option, } +#[derive(Debug, PartialEq)] +pub struct SetIfAbsent { + pub key: Arc<[u8]>, + pub value: Bytes, +} + +#[derive(Debug, PartialEq)] +pub struct SetIfPresentAndNotEqual { + pub key: Arc<[u8]>, + pub new_value: Bytes, + pub old_value: Bytes, +} + +#[derive(Debug, PartialEq)] +pub struct ItemGetType { + pub key: Arc<[u8]>, +} + // Hash #[derive(Debug, PartialEq)] @@ -212,6 +230,9 @@ pub enum ClientRequest { MultiGet(MultiGet), Replace(Replace), Set(Set), + SetIfAbsent(SetIfAbsent), + SetIfPresentAndNotEqual(SetIfPresentAndNotEqual), + ItemGetType(ItemGetType), // Hash Commands HashExists(HashExists), diff --git a/src/workload/mod.rs b/src/workload/mod.rs index 2c26066e..cff77122 100644 --- a/src/workload/mod.rs +++ b/src/workload/mod.rs @@ -370,6 +370,20 @@ impl Generator { Verb::Delete => ClientRequest::Delete(client::Delete { key: keyspace.sample(rng), }), + Verb::SetIfAbsent => ClientRequest::SetIfAbsent(client::SetIfAbsent { + key: keyspace.sample(rng), + value: keyspace.gen_value(sequence as _, rng), + }), + Verb::SetIfPresentAndNotEqual => { + ClientRequest::SetIfPresentAndNotEqual(client::SetIfPresentAndNotEqual { + key: keyspace.sample(rng), + new_value: keyspace.gen_value(sequence as _, rng), + old_value: keyspace.gen_value(sequence as _, rng), + }) + } + Verb::ItemGetType => ClientRequest::ItemGetType(client::ItemGetType { + key: keyspace.sample(rng), + }), Verb::Replace => ClientRequest::Replace(client::Replace { key: keyspace.sample(rng), value: keyspace.gen_value(sequence as _, rng),