Skip to content

Commit bf2b3a6

Browse files
authored
Add new API to remove expiration for RedisKeyWritable. (#276)
1 parent b918ed0 commit bf2b3a6

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ crate-type = ["cdylib"]
116116
name = "open_key_with_flags"
117117
crate-type = ["cdylib"]
118118

119+
[[example]]
120+
name = "expire"
121+
crate-type = ["cdylib"]
122+
119123
[dependencies]
120124
bitflags = "2"
121125
libc = "0.2"

examples/expire.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use redis_module::{redis_module, Context, NextArg, RedisError, RedisResult, RedisString};
2+
use std::time::Duration;
3+
4+
fn expire_cmd(ctx: &Context, args: Vec<RedisString>) -> RedisResult {
5+
if args.len() < 3 {
6+
return Err(RedisError::WrongArity);
7+
}
8+
9+
let mut args = args.into_iter().skip(1);
10+
let key_name = args.next_arg()?;
11+
let ttl_sec = args.next_i64()?;
12+
let key = ctx.open_key_writable(&key_name);
13+
if ttl_sec >= 0 {
14+
key.set_expire(Duration::new(ttl_sec as u64, 0))
15+
} else {
16+
key.remove_expire()
17+
}
18+
}
19+
20+
//////////////////////////////////////////////////////
21+
22+
redis_module! {
23+
name: "expire",
24+
version: 1,
25+
allocator: (redis_module::alloc::RedisAlloc, redis_module::alloc::RedisAlloc),
26+
data_types: [],
27+
commands: [
28+
["expire.cmd", expire_cmd, "write fast deny-oom", 1, 1, 1],
29+
],
30+
}

src/key.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,17 @@ impl RedisKeyWritable {
337337
}
338338
}
339339

340+
/// Remove expiration from a key if it exists.
341+
pub fn remove_expire(&self) -> RedisResult {
342+
match raw::set_expire(self.key_inner, REDISMODULE_NO_EXPIRE.into()) {
343+
raw::Status::Ok => REDIS_OK,
344+
345+
// Error may occur if the key wasn't open for writing or is an
346+
// empty key.
347+
raw::Status::Err => Err(RedisError::Str("Error while removing key expire")),
348+
}
349+
}
350+
340351
pub fn write(&self, val: &str) -> RedisResult {
341352
let val_str = RedisString::create(NonNull::new(self.ctx), val);
342353
match raw::string_set(self.key_inner, val_str.inner) {

tests/integration.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,3 +705,41 @@ fn test_open_key_with_flags() -> Result<()> {
705705

706706
Ok(())
707707
}
708+
709+
#[test]
710+
fn test_expire() -> Result<()> {
711+
let port: u16 = 6502;
712+
let _guards = vec![start_redis_server_with_module("expire", port)
713+
.with_context(|| "failed to start redis server")?];
714+
let mut con =
715+
get_redis_connection(port).with_context(|| "failed to connect to redis server")?;
716+
717+
// Create a key without TTL
718+
redis::cmd("set")
719+
.arg(&["key", "value"])
720+
.query(&mut con)
721+
.with_context(|| "failed to run set")?;
722+
723+
let ttl: i64 = redis::cmd("ttl").arg(&["key"]).query(&mut con)?;
724+
assert_eq!(ttl, -1);
725+
726+
// Set TTL on the key
727+
redis::cmd("expire.cmd")
728+
.arg(&["key", "100"])
729+
.query(&mut con)
730+
.with_context(|| "failed to run expire.cmd")?;
731+
732+
let ttl: i64 = redis::cmd("ttl").arg(&["key"]).query(&mut con)?;
733+
assert!(ttl > 0);
734+
735+
// Remove TTL on the key
736+
redis::cmd("expire.cmd")
737+
.arg(&["key", "-1"])
738+
.query(&mut con)
739+
.with_context(|| "failed to run expire.cmd")?;
740+
741+
let ttl: i64 = redis::cmd("ttl").arg(&["key"]).query(&mut con)?;
742+
assert_eq!(ttl, -1);
743+
744+
Ok(())
745+
}

0 commit comments

Comments
 (0)