Skip to content

API proposal: keyspace notifications #2984

@mgravell

Description

@mgravell

Regular pubsub does not work well with keyspace notifications due to the different routing requirements, and the complexity of understanding the key and event type. A new API is suggested:

+ public enum KeyspaceEvent
+ { 
+     Unknown,
+     All,
+     // see list https://redis.io/docs/latest/develop/pubsub/keyspace-notifications/  
+     Add,
+     // ...
+     ZRem,
+     Expired,
+     // ...
+     TypeChanged // type_changed
+ }
+ public readonly struct KeyspaceNotification(int database, in RedisKey key, KeyspaceEvent @event)
+ {
+     public int Database => database;
+     public RedisKey Key => key;
+     public KeyspaceEvent Event => @event;
+ }
  public readonly struct RedisChannel
  {
+     // if this channel corresponds to a keyspace/keyevent notification: parse out the key, event and database information from the channel and payload
+     public bool IsKeyspaceNotification(in RedisValue value, out KeyspaceNotification notification);
+     // subscribe to keyevent notifications of the given category (or All), i.e. __keyevent@{database}__:{event}
+     public static RedisChannel KeyEventNotification(KeyspaceEvent @event, int? database = null);
+     // subscribe to keyspace notifications for the given key, i.e. __keyspace@{database}__:{key}
+     public static RedisChannel KeySpaceNotification(RedisKey key, int? database = null);
+     // subscribe to keyspace notifications for the given pattern, i.e. __keyspace@{database}__:{pattern}
+     public static RedisChannel KeySpacePatternNotification(RedisKey pattern, int? database = null);
  }
  public readonly struct ChannelMessage
  {
+     public bool IsKeyspaceNotification(out KeyspaceNotification notification) => Channel.IsKeyspaceNotification(Message, out notification);
  }

Note that the int? database in this context refers to single database vs all databases; if the value is -ve, the default database will be applied, but the assumption is that we mean any database. In the case of "any database", or KeySpacePatternNotification, PSUBSCRIBE will be used, otherwise SUBSCRIBE will be used. In the case of cluster, KeyEventNotification and KeySpacePatternNotification require routing to all endpoints. Note that vanilla redis limits cluster to single-database (zero); while this generalization may not hold in all cases (Valkey), SE.Redis does not properly support that scenario.

Internally, additional work will be required for OSS cluster to ensure all primary nodes are covered, including reconnects and topology changes; this changes the existing expectation that a channel has zero or one connected endpoints, so is non-trivial.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions