Keyspace event for new keys (#10512)
Add an optional keyspace event when new keys are added to the db. This is useful for applications where clients need to be aware of the redis keyspace. Such an application can SCAN once at startup and then listen for "new" events (plus others associated with DEL, RENAME, etc).
This commit is contained in:
parent
e875ff89ec
commit
bb7891f080
@ -1827,6 +1827,7 @@ latency-monitor-threshold 0
|
||||
# z Sorted set commands
|
||||
# x Expired events (events generated every time a key expires)
|
||||
# e Evicted events (events generated when a key is evicted for maxmemory)
|
||||
# n New key events (Note: not included in the 'A' class)
|
||||
# t Stream commands
|
||||
# d Module key type events
|
||||
# m Key-miss events (Note: It is not included in the 'A' class)
|
||||
|
@ -2691,7 +2691,7 @@ static int setConfigNotifyKeyspaceEventsOption(standardConfig *config, sds *argv
|
||||
}
|
||||
int flags = keyspaceEventsStringToFlags(argv[0]);
|
||||
if (flags == -1) {
|
||||
*err = "Invalid event class character. Use 'Ag$lshzxeKEtmd'.";
|
||||
*err = "Invalid event class character. Use 'Ag$lshzxeKEtmdn'.";
|
||||
return 0;
|
||||
}
|
||||
server.notify_keyspace_events = flags;
|
||||
|
1
src/db.c
1
src/db.c
@ -182,6 +182,7 @@ void dbAdd(redisDb *db, robj *key, robj *val) {
|
||||
dictSetVal(db->dict, de, val);
|
||||
signalKeyAsReady(db, key, val->type);
|
||||
if (server.cluster_enabled) slotToKeyAddEntry(de, db);
|
||||
notifyKeyspaceEvent(NOTIFY_NEW,"new",key,db->id);
|
||||
}
|
||||
|
||||
/* This is a special version of dbAdd() that is used only when loading
|
||||
|
@ -57,6 +57,7 @@ int keyspaceEventsStringToFlags(char *classes) {
|
||||
case 't': flags |= NOTIFY_STREAM; break;
|
||||
case 'm': flags |= NOTIFY_KEY_MISS; break;
|
||||
case 'd': flags |= NOTIFY_MODULE; break;
|
||||
case 'n': flags |= NOTIFY_NEW; break;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
@ -84,6 +85,7 @@ sds keyspaceEventsFlagsToString(int flags) {
|
||||
if (flags & NOTIFY_EVICTED) res = sdscatlen(res,"e",1);
|
||||
if (flags & NOTIFY_STREAM) res = sdscatlen(res,"t",1);
|
||||
if (flags & NOTIFY_MODULE) res = sdscatlen(res,"d",1);
|
||||
if (flags & NOTIFY_NEW) res = sdscatlen(res,"n",1);
|
||||
}
|
||||
if (flags & NOTIFY_KEYSPACE) res = sdscatlen(res,"K",1);
|
||||
if (flags & NOTIFY_KEYEVENT) res = sdscatlen(res,"E",1);
|
||||
|
@ -603,6 +603,7 @@ typedef enum {
|
||||
#define NOTIFY_KEY_MISS (1<<11) /* m (Note: This one is excluded from NOTIFY_ALL on purpose) */
|
||||
#define NOTIFY_LOADED (1<<12) /* module only key space notification, indicate a key loaded from rdb */
|
||||
#define NOTIFY_MODULE (1<<13) /* d, module key space notification */
|
||||
#define NOTIFY_NEW (1<<14) /* n, new key notification */
|
||||
#define NOTIFY_ALL (NOTIFY_GENERIC | NOTIFY_STRING | NOTIFY_LIST | NOTIFY_SET | NOTIFY_HASH | NOTIFY_ZSET | NOTIFY_EXPIRED | NOTIFY_EVICTED | NOTIFY_STREAM | NOTIFY_MODULE) /* A flag */
|
||||
|
||||
/* Using the following macro you can run code inside serverCron() with the
|
||||
|
@ -390,4 +390,17 @@ start_server {tags {"pubsub network"}} {
|
||||
r config set notify-keyspace-events EA
|
||||
assert_equal {AE} [lindex [r config get notify-keyspace-events] 1]
|
||||
}
|
||||
|
||||
test "Keyspace notifications: new key test" {
|
||||
r config set notify-keyspace-events En
|
||||
set rd1 [redis_deferring_client]
|
||||
assert_equal {1} [psubscribe $rd1 *]
|
||||
r set foo bar
|
||||
# second set of foo should not cause a 'new' event
|
||||
r set foo baz
|
||||
r set bar bar
|
||||
assert_equal "pmessage * __keyevent@${db}__:new foo" [$rd1 read]
|
||||
assert_equal "pmessage * __keyevent@${db}__:new bar" [$rd1 read]
|
||||
$rd1 close
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user