Skip to content

Commit

Permalink
Add new API to remove expiration for RedisKeyWritable.
Browse files Browse the repository at this point in the history
  • Loading branch information
QuChen88 committed Jan 30, 2024
1 parent 2aafa4a commit 49d4179
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ crate-type = ["cdylib"]
name = "open_key_with_flags"
crate-type = ["cdylib"]

[[example]]
name = "expire"
crate-type = ["cdylib"]

[dependencies]
bitflags = "2"
libc = "0.2"
Expand Down
30 changes: 30 additions & 0 deletions examples/expire.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use redis_module::{redis_module, Context, NextArg, RedisError, RedisResult, RedisString};
use std::time::Duration;

fn expire_cmd(ctx: &Context, args: Vec<RedisString>) -> RedisResult {
if args.len() < 3 {
return Err(RedisError::WrongArity);
}

let mut args = args.into_iter().skip(1);
let key_name = args.next_arg()?;
let ttl_sec = args.next_i64()?;
let key = ctx.open_key_writable(&key_name);
if ttl_sec >= 0 {
key.set_expire(Duration::new(ttl_sec as u64, 0))
} else {
key.remove_expire()
}
}

//////////////////////////////////////////////////////

redis_module! {
name: "expire",
version: 1,
allocator: (redis_module::alloc::RedisAlloc, redis_module::alloc::RedisAlloc),
data_types: [],
commands: [
["expire.cmd", expire_cmd, "write fast deny-oom", 1, 1, 1],
],
}
11 changes: 11 additions & 0 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,17 @@ impl RedisKeyWritable {
}
}

/// Remove expiration from a key if it exists.
pub fn remove_expire(&self) -> RedisResult {
match raw::set_expire(self.key_inner, REDISMODULE_NO_EXPIRE.into()) {
raw::Status::Ok => REDIS_OK,

// Error may occur if the key wasn't open for writing or is an
// empty key.
raw::Status::Err => Err(RedisError::Str("Error while removing key expire")),
}
}

pub fn write(&self, val: &str) -> RedisResult {
let val_str = RedisString::create(NonNull::new(self.ctx), val);
match raw::string_set(self.key_inner, val_str.inner) {
Expand Down
38 changes: 38 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,3 +705,41 @@ fn test_open_key_with_flags() -> Result<()> {

Ok(())
}

#[test]
fn test_expire() -> Result<()> {
let port: u16 = 6502;
let _guards = vec![start_redis_server_with_module("expire", port)
.with_context(|| "failed to start redis server")?];
let mut con =
get_redis_connection(port).with_context(|| "failed to connect to redis server")?;

// Create a key without TTL
redis::cmd("set")
.arg(&["key", "value"])
.query(&mut con)
.with_context(|| "failed to run set")?;

let ttl: i64 = redis::cmd("ttl").arg(&["key"]).query(&mut con)?;
assert_eq!(ttl, -1);

// Set TTL on the key
redis::cmd("expire.cmd")
.arg(&["key", "100"])
.query(&mut con)
.with_context(|| "failed to run expire.cmd")?;

let ttl: i64 = redis::cmd("ttl").arg(&["key"]).query(&mut con)?;
assert!(ttl > 0);

// Remove TTL on the key
redis::cmd("expire.cmd")
.arg(&["key", "-1"])
.query(&mut con)
.with_context(|| "failed to run expire.cmd")?;

let ttl: i64 = redis::cmd("ttl").arg(&["key"]).query(&mut con)?;
assert_eq!(ttl, -1);

Ok(())
}

0 comments on commit 49d4179

Please sign in to comment.