diff --git a/crates/ember-client/src/commands.rs b/crates/ember-client/src/commands.rs index a157d459..03a2ad42 100644 --- a/crates/ember-client/src/commands.rs +++ b/crates/ember-client/src/commands.rs @@ -790,6 +790,26 @@ impl Client { integer(frame) } + /// Increments the integer stored at `field` in the hash at `key` by + /// `delta`. Returns the new value. + pub async fn hincrby( + &mut self, + key: &str, + field: &str, + delta: i64, + ) -> Result { + let d = delta.to_string(); + let frame = self + .send_frame(cmd4( + b"HINCRBY", + key.as_bytes(), + field.as_bytes(), + d.as_bytes(), + )) + .await?; + integer(frame) + } + /// Returns all field names in the hash at `key`. pub async fn hkeys(&mut self, key: &str) -> Result, ClientError> { let frame = self.send_frame(cmd2(b"HKEYS", key.as_bytes())).await?; diff --git a/crates/ember-client/src/pipeline.rs b/crates/ember-client/src/pipeline.rs index 4a3f4039..94b69e52 100644 --- a/crates/ember-client/src/pipeline.rs +++ b/crates/ember-client/src/pipeline.rs @@ -168,6 +168,17 @@ impl Pipeline { self.push(array_with_key_and_keys(b"HDEL", key, fields)) } + /// Queues an `HINCRBY key field delta` command. + pub fn hincrby(self, key: &str, field: &str, delta: i64) -> Self { + let d = delta.to_string(); + self.push(Frame::Array(vec![ + Frame::Bulk(Bytes::from_static(b"HINCRBY")), + Frame::Bulk(Bytes::copy_from_slice(key.as_bytes())), + Frame::Bulk(Bytes::copy_from_slice(field.as_bytes())), + Frame::Bulk(Bytes::copy_from_slice(d.as_bytes())), + ])) + } + // --- set commands --- /// Queues an `SADD key member [member ...]` command. diff --git a/tests/integration/src/client_typed_api.rs b/tests/integration/src/client_typed_api.rs index 69278afb..147e5713 100644 --- a/tests/integration/src/client_typed_api.rs +++ b/tests/integration/src/client_typed_api.rs @@ -147,6 +147,18 @@ async fn hget_missing_field() { assert!(client.hget("h", "missing").await.unwrap().is_none()); } +// --- hincrby --- + +#[tokio::test] +async fn hincrby_increments_and_returns_new_value() { + let (_server, mut client) = connect().await; + client.hset("counter", &[("hits", "10")]).await.unwrap(); + assert_eq!(client.hincrby("counter", "hits", 5).await.unwrap(), 15); + assert_eq!(client.hincrby("counter", "hits", -3).await.unwrap(), 12); + // field created on first call if missing + assert_eq!(client.hincrby("counter", "new_field", 1).await.unwrap(), 1); +} + // --- sorted set commands --- #[tokio::test]