Modules hooks: a first version of events and some API.

This commit is contained in:
antirez 2019-10-21 17:16:34 +02:00
parent 3170f63330
commit bebb2e1994
2 changed files with 120 additions and 7 deletions

View File

@ -345,13 +345,6 @@ static struct RedisModuleForkInfo {
#define REDISMODULE_EVENT_ID_MASTER_LINK_UP 14
#define REDISMODULE_EVENT_ID_MASTER_LINK_DOWN 15
typedef struct RedisModuleEvent {
uint64_t id; /* REDISMODULE_EVENT_ID_... defines. */
uint64_t dataver; /* Version of the structure we pass as 'data'. */
} RedisModuleEvent;
typedef int (*RedisModuleEventCallback)(RedisModuleEvent eid, void *data);
typedef struct RedisModuleEventListener {
RedisModule *module;
RedisModuleEvent event;
@ -5587,6 +5580,57 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) {
moduleForkInfo.done_handler_user_data = NULL;
}
/* --------------------------------------------------------------------------
* Server hooks implementation
* -------------------------------------------------------------------------- */
/* Register to be notified, via a callback, when the specified server event
* happens. The callback is called with the event as argument, and an additional
* argument which is a void pointer and should be cased to a specific type
* that is event-specific (but many events will just use NULL since they do not
* have additional information to pass to the callback).
*
* If the callback is NULL and there was a previous subscription, the module
* will be unsubscribed. If there was a previous subscription and the callback
* is not null, the old callback will be replaced with the new one.
*
* The function returns REDISMODULE_OK if the module was successfully subscrived
* for the specified event. If the API is called from a wrong context then
* REDISMODULE_ERR is returned. */
int RedisModule_SubscribeToServerEvent(RedisModuleCtx *ctx, RedisModuleEvent event, RedisModuleEventCallback callback) {
RedisModuleEventListener *el;
/* Protect in case of calls from contexts without a module reference. */
if (ctx->module == NULL) return REDISMODULE_ERR;
/* Search an event matching this module and event ID. */
listIter li;
listNode *ln;
listRewind(RedisModule_EventListeners,&li);
while((ln = listNext(&li))) {
el = ln->value;
if (el->module == ctx->module && el->event.id == event.id)
break; /* Matching event found. */
}
/* Modify or remove the event listener if we already had one. */
if (ln) {
if (callback == NULL)
listDelNode(RedisModule_EventListeners,ln);
else
el->callback = callback; /* Update the callback with the new one. */
return REDISMODULE_OK;
}
/* No event found, we need to add a new one. */
el = zmalloc(sizeof(*el));
el->module = ctx->module;
el->event = event;
el->callback = callback;
listAddNodeTail(RedisModule_EventListeners,el);
return REDISMODULE_OK;
}
/* --------------------------------------------------------------------------
* Modules API internals
* -------------------------------------------------------------------------- */

View File

@ -162,6 +162,75 @@ typedef uint64_t RedisModuleTimerID;
/* Declare that the module can handle errors with RedisModule_SetModuleOptions. */
#define REDISMODULE_OPTIONS_HANDLE_IO_ERRORS (1<<0)
/* Server events definitions. */
#define REDISMODULE_EVENT_ID_REPLICATION_ROLE_CHANGED 0
#define REDISMODULE_EVENT_ID_PERSISTENCE 1
#define REDISMODULE_EVENT_ID_FLUSHDB 2
#define REDISMODULE_EVENT_ID_LOADING 3
#define REDISMODULE_EVENT_ID_CLIENT_CHANGE 4
#define REDISMODULE_EVENT_ID_SHUTDOWN 5
#define REDISMODULE_EVENT_ID_REPLICA_CHANGE 6
#define REDISMODULE_EVENT_ID_MASTER_LINK_CHANGE 7
typedef struct RedisModuleEvent {
uint64_t id; /* REDISMODULE_EVENT_ID_... defines. */
uint64_t dataver; /* Version of the structure we pass as 'data'. */
} RedisModuleEvent;
RedisModuleEvent
RedisModuleEvent_ReplicationRoleChanged = {
REDISMODULE_EVENT_ID_REPLICATION_ROLE_CHANGED,
0
},
RedisModuleEvent_Persistence = {
REDISMODULE_EVENT_ID_PERSISTENCE,
0
},
RedisModuleEvent_FlushDB = {
REDISMODULE_EVENT_ID_FLUSHDB,
0
},
RedisModuleEvent_Loading = {
REDISMODULE_EVENT_ID_LOADING,
0
},
RedisModuleEvent_ClientChange = {
REDISMODULE_EVENT_ID_CLIENT_CHANGE,
0
},
RedisModuleEvent_Shutdown = {
REDISMODULE_EVENT_ID_SHUTDOWN,
0
},
RedisModuleEvent_ReplicaChange = {
REDISMODULE_EVENT_ID_REPLICA_CHANGE,
0
},
RedisModuleEvent_MasterLinkChange = {
REDISMODULE_EVENT_ID_MASTER_LINK_CHANGE,
0
};
typedef int (*RedisModuleEventCallback)(RedisModuleEvent eid, uint64_t subevent, void *data);
/* Those are values that are used for the 'subevent' callback argument. */
#define REDISMODULE_EVENT_PERSISTENCE_RDB_START 0
#define REDISMODULE_EVENT_PERSISTENCE_RDB_END 1
#define REDISMODULE_EVENT_PERSISTENCE_AOF_START 2
#define REDISMODULE_EVENT_PERSISTENCE_AOF_END 3
#define REDISMODULE_EVENT_LOADING_START 0
#define REDISMODULE_EVENT_LOADING_END 1
#define REDISMODULE_EVENT_CLIENT_CHANGE_CONNECTED 0
#define REDISMODULE_EVENT_CLIENT_CHANGE_DISCONNECTED 1
#define REDISMODULE_EVENT_MASTER_LINK_UP 0
#define REDISMODULE_EVENT_MASTER_LINK_DOWN 1
#define REDISMODULE_EVENT_REPLICA_CHANGE_CONNECTED 0
#define REDISMODULE_EVENT_REPLICA_CHANGE_DISCONNECTED 1
/* ------------------------- End of common defines ------------------------ */
#ifndef REDISMODULE_CORE