use redis_module::{
key::{KeyFlags, RedisKey},
redis_module, Context, KeysCursor, RedisError, RedisResult, RedisString, RedisValue,
ScanKeyCursor,
};
fn scan_keys(ctx: &Context, _args: Vec<RedisString>) -> RedisResult {
let cursor = KeysCursor::new();
let mut res = Vec::new();
let scan_callback = |ctx: &Context, key_name: &RedisString, _key: Option<&RedisKey>| {
res.push(RedisValue::BulkRedisString(key_name.safe_clone(ctx)));
};
while cursor.scan(ctx, &scan_callback) {
}
Ok(RedisValue::Array(res))
}
fn scan_key(ctx: &Context, args: Vec<RedisString>) -> RedisResult {
if args.len() != 2 {
return Err(RedisError::WrongArity);
}
let key_name = &args[1];
let key = ctx.open_key_with_flags(
key_name,
KeyFlags::NOEFFECTS | KeyFlags::NOEXPIRE | KeyFlags::ACCESS_EXPIRED,
);
let cursor = ScanKeyCursor::new(key);
let mut res = Vec::new();
while cursor.scan(|_key, field, value| {
res.push(RedisValue::BulkRedisString(field.clone()));
res.push(RedisValue::BulkRedisString(value.clone()));
}) {
}
Ok(RedisValue::Array(res))
}
fn scan_key_for_each(ctx: &Context, args: Vec<RedisString>) -> RedisResult {
if args.len() != 2 {
return Err(RedisError::WrongArity);
}
let key_name = &args[1];
let key = ctx.open_key_with_flags(
key_name,
KeyFlags::NOEFFECTS | KeyFlags::NOEXPIRE | KeyFlags::ACCESS_EXPIRED,
);
let cursor = ScanKeyCursor::new(key);
let mut res = Vec::new();
cursor.for_each(|_key, field, value| {
res.push(RedisValue::BulkRedisString(field.clone()));
res.push(RedisValue::BulkRedisString(value.clone()));
});
Ok(RedisValue::Array(res))
}
redis_module! {
name: "scan",
version: 1,
allocator: (redis_module::alloc::RedisAlloc, redis_module::alloc::RedisAlloc),
data_types: [],
commands: [
["scan_keys", scan_keys, "readonly", 0, 0, 0, ""],
["scan_key", scan_key, "readonly", 0, 0, 0, ""],
["scan_key_for_each", scan_key_for_each, "readonly", 0, 0, 0, ""],
],
}