summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Palmer <luke@lukepalmer.net>2022-04-13 04:36:38 -0400
committerGitHub <noreply@github.com>2022-04-13 11:36:38 +0300
commitbb7891f080602fb92197a0f398be71eb7aba9e3c (patch)
tree8e10bb0b29c09543714c5266c7e2ac757aaab442
parente875ff89ece5ec9d43273b19e3b88e4d36a48ba9 (diff)
downloadredis-bb7891f080602fb92197a0f398be71eb7aba9e3c.tar.gz
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).
-rw-r--r--redis.conf1
-rw-r--r--src/config.c2
-rw-r--r--src/db.c1
-rw-r--r--src/notify.c2
-rw-r--r--src/server.h1
-rw-r--r--tests/unit/pubsub.tcl13
6 files changed, 19 insertions, 1 deletions
diff --git a/redis.conf b/redis.conf
index 34b755718..4fbbaf7e0 100644
--- a/redis.conf
+++ b/redis.conf
@@ -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)
diff --git a/src/config.c b/src/config.c
index 3b5d4d349..cb3ff2e45 100644
--- a/src/config.c
+++ b/src/config.c
@@ -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;
diff --git a/src/db.c b/src/db.c
index d4da756f1..10da1e923 100644
--- a/src/db.c
+++ b/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
diff --git a/src/notify.c b/src/notify.c
index 28c0048cb..633e35bdc 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -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);
diff --git a/src/server.h b/src/server.h
index 37f7f3d7e..65727cd40 100644
--- a/src/server.h
+++ b/src/server.h
@@ -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
diff --git a/tests/unit/pubsub.tcl b/tests/unit/pubsub.tcl
index 4435a9b1d..ea8964cf3 100644
--- a/tests/unit/pubsub.tcl
+++ b/tests/unit/pubsub.tcl
@@ -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
+ }
}