use std::ops::Deref;
use std::sync::RwLock;
use valkey_module::alloc::ValkeyAlloc;
use valkey_module::logging::log_notice;
use valkey_module::{
valkey_module, CommandFilter, CommandFilterCtx, Context, RedisModuleCommandFilterCtx, Status,
ValkeyResult, ValkeyString, VALKEYMODULE_CMDFILTER_NOSELF,
};
static INFO_FILTER: RwLock<Option<CommandFilter>> = RwLock::new(None);
fn init(ctx: &Context, _args: &[ValkeyString]) -> Status {
let info_filter = ctx.register_command_filter(info_filter_fn, VALKEYMODULE_CMDFILTER_NOSELF);
if info_filter.is_null() {
return Status::Err;
}
let mut info_guard = INFO_FILTER.write().unwrap();
*info_guard = Some(info_filter);
Status::Ok
}
fn deinit(ctx: &Context) -> Status {
let info_guard = INFO_FILTER.read().unwrap();
if let Some(ref info_filter) = info_guard.deref() {
ctx.unregister_command_filter(info_filter);
};
Status::Ok
}
extern "C" fn info_filter_fn(ctx: *mut RedisModuleCommandFilterCtx) {
let cf_ctx = CommandFilterCtx::new(ctx);
if cf_ctx.args_count() != 1 {
return;
}
let cmd = cf_ctx.arg_get_try_as_str(0).unwrap();
if !cmd.eq_ignore_ascii_case("info") {
return;
}
let client_id = cf_ctx.get_client_id();
log_notice(&format!("info filter for client_id {}", client_id));
cf_ctx.arg_replace(0, "info2");
}
fn info2(ctx: &Context, _args: Vec<ValkeyString>) -> ValkeyResult {
ctx.log_notice("info2 command");
Ok("info2\n".into())
}
fn set_filter_fn(ctx: *mut RedisModuleCommandFilterCtx) {
let cf_ctx = CommandFilterCtx::new(ctx);
if cf_ctx.args_count() != 3 {
return;
}
let cmd = cf_ctx.cmd_get_try_as_str().unwrap();
if !cmd.eq_ignore_ascii_case("set") {
return;
}
let all_args = cf_ctx.get_all_args_wo_cmd();
log_notice(&format!("all_args: {:?}", all_args));
let key = cf_ctx.arg_get_try_as_str(1).unwrap();
let value = cf_ctx.arg_get_try_as_str(2).unwrap();
log_notice(&format!("set key: {}, value {}", key, value));
cf_ctx.arg_delete(1);
cf_ctx.arg_insert(1, "new_key");
cf_ctx.arg_replace(2, "new_value");
}
fn filter1_fn(_ctx: *mut RedisModuleCommandFilterCtx) {
}
fn filter2_fn(_ctx: *mut RedisModuleCommandFilterCtx) {
}
valkey_module! {
name: "filter1",
version: 1,
allocator: (ValkeyAlloc, ValkeyAlloc),
data_types: [],
init: init,
deinit: deinit,
commands: [
["info2", info2, "readonly", 0, 0, 0],
],
filters: [
[set_filter_fn, VALKEYMODULE_CMDFILTER_NOSELF],
[filter1_fn, VALKEYMODULE_CMDFILTER_NOSELF],
[filter2_fn, VALKEYMODULE_CMDFILTER_NOSELF]
]
}