• Huang Zhw's avatar
    Add a special notification unlink available only for modules (#9406) · c8181314
    Huang Zhw authored
    
    
    Add a new module event `RedisModule_Event_Key`, this event is fired
    when a key is removed from the keyspace.
    The event includes an open key that can be used for reading the key before
    it is removed. Modules can also extract the key-name, and use RM_Open
    or RM_Call to access key from within that event, but shouldn't modify anything
    from within this event.
    
    The following sub events are available:
      - `REDISMODULE_SUBEVENT_KEY_DELETED`
      - `REDISMODULE_SUBEVENT_KEY_EXPIRED`
      - `REDISMODULE_SUBEVENT_KEY_EVICTED`
      - `REDISMODULE_SUBEVENT_KEY_OVERWRITE`
    
    The data pointer can be casted to a RedisModuleKeyInfo structure
    with the following fields:
    ```
         RedisModuleKey *key;    // Opened Key
     ```
    
    ### internals
    
    * We also add two dict functions:
      `dictTwoPhaseUnlinkFind` finds an element from the table, also get the plink of the entry.
      The entry is returned if the element is found. The user should later call `dictTwoPhaseUnlinkFree`
      with it in order to unlink and release it. Otherwise if the key is not found, NULL is returned.
      These two functions should be used in pair. `dictTwoPhaseUnlinkFind` pauses rehash and
      `dictTwoPhaseUnlinkFree` resumes rehash.
    * We change `dbOverwrite` to `dbReplaceValue` which just replaces the value of the key and
      doesn't fire any events. The "overwrite" part (which emits events) is just when called from `setKey`,
      the other places that called dbOverwrite were ones that just update the value in-place (INCR*, SPOP,
      and dbUnshareStringValue). This should not have any real impact since `moduleNotifyKeyUnlink` and
      `signalDeletedKeyAsReady` wouldn't have mattered in these cases anyway (i.e. module keys and
      stream keys didn't have direct calls to dbOverwrite)
    * since we allow doing RM_OpenKey from withing these callbacks, we temporarily disable lazy expiry.
    * We also temporarily disable lazy expiry when we are in unlink/unlink2 callback and keyspace 
      notification callback.
    * Move special definitions to the top of redismodule.h
      This is needed to resolve compilation errors with RedisModuleKeyInfoV1
      that carries a RedisModuleKey member.
    Co-authored-by: default avatarOran Agra <oran@redislabs.com>
    c8181314
t_set.c 57.5 KB