- Fix #1253: Cache entries fail to be removed from Redis cachedb

backend with unbound-control flush* +c.
This commit is contained in:
W.C.A. Wijngaards 2025-03-21 12:56:21 +01:00
parent eccf52e39d
commit a42fb99508
2 changed files with 28 additions and 15 deletions

View file

@ -61,7 +61,7 @@ struct redis_moddata {
struct timeval command_timeout; /* timeout for commands */ struct timeval command_timeout; /* timeout for commands */
struct timeval connect_timeout; /* timeout for connect */ struct timeval connect_timeout; /* timeout for connect */
int logical_db; /* the redis logical database to use */ int logical_db; /* the redis logical database to use */
int setex_available; /* if the SETEX command is supported */ int set_with_ex_available; /* if the SET with EX command is supported */
}; };
static redisReply* redis_command(struct module_env*, struct cachedb_env*, static redisReply* redis_command(struct module_env*, struct cachedb_env*,
@ -195,12 +195,12 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
moddata->ctxs[env->alloc->thread_num] != NULL) { moddata->ctxs[env->alloc->thread_num] != NULL) {
redisReply* rep = NULL; redisReply* rep = NULL;
int redis_reply_type = 0; int redis_reply_type = 0;
/** check if setex command is supported */ /** check if set with ex command is supported */
rep = redis_command(env, cachedb_env, rep = redis_command(env, cachedb_env,
"SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0); "SET __UNBOUND_REDIS_CHECK__ none EX 1", NULL, 0);
if(!rep) { if(!rep) {
/** init failed, no response from redis server*/ /** init failed, no response from redis server*/
goto setex_fail; goto set_with_ex_fail;
} }
redis_reply_type = rep->type; redis_reply_type = rep->type;
freeReplyObject(rep); freeReplyObject(rep);
@ -208,17 +208,17 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
case REDIS_REPLY_STATUS: case REDIS_REPLY_STATUS:
break; break;
default: default:
/** init failed, setex command not supported */ /** init failed, set_with_ex command not supported */
goto setex_fail; goto set_with_ex_fail;
} }
moddata->setex_available = 1; moddata->set_with_ex_available = 1;
} }
return 1; return 1;
setex_fail: set_with_ex_fail:
log_err("redis_init: failure during redis_init, the " log_err("redis_init: failure during redis_init, the "
"redis-expire-records option requires the SETEX command " "redis-expire-records option requires the SET with EX command "
"(redis >= 2.0.0)"); "(redis >= 2.6.2)");
return 1; return 1;
fail: fail:
moddata_clean(&moddata); moddata_clean(&moddata);
@ -352,12 +352,14 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
int n; int n;
struct redis_moddata* moddata = (struct redis_moddata*) struct redis_moddata* moddata = (struct redis_moddata*)
cachedb_env->backend_data; cachedb_env->backend_data;
int set_ttl = (moddata->setex_available && int set_ttl = (moddata->set_with_ex_available &&
env->cfg->redis_expire_records && env->cfg->redis_expire_records &&
(!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0)); (!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
/* Supported commands: /* Supported commands:
* - "SET " + key + " %b" * - "SET " + key + " %b"
* - "SETEX " + key + " " + ttl + " %b" * - "SET " + key + " %b EX " + ttl
* older redis 2.0.0 was "SETEX " + key + " " + ttl + " %b"
* - "EXPIRE " + key + " 0"
*/ */
char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1]; char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
@ -365,14 +367,21 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len); verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
/* build command to set to a binary safe string */ /* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key); n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
} else if(ttl == 0) {
/* use the EXPIRE command, SET with EX 0 is an invalid time. */
verbose(VERB_ALGO, "redis_store expire %s (%d bytes)",
key, (int)data_len);
n = snprintf(cmdbuf, sizeof(cmdbuf), "EXPIRE %s 0", key);
data = NULL;
data_len = 0;
} else { } else {
/* add expired ttl time to redis ttl to avoid premature eviction of key */ /* add expired ttl time to redis ttl to avoid premature eviction of key */
ttl += env->cfg->serve_expired_ttl; ttl += env->cfg->serve_expired_ttl;
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u", verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
key, (int)data_len, (uint32_t)ttl); key, (int)data_len, (unsigned)(uint32_t)ttl);
/* build command to set to a binary safe string */ /* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key, n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b EX %u", key,
(uint32_t)ttl); (unsigned)(uint32_t)ttl);
} }

View file

@ -1,3 +1,7 @@
21 March 2025: Wouter
- Fix #1253: Cache entries fail to be removed from Redis cachedb
backend with unbound-control flush* +c.
20 March 2025: Wouter 20 March 2025: Wouter
- Fix print of RR type NSAP-PTR, it is an unquoted string. - Fix print of RR type NSAP-PTR, it is an unquoted string.