Minor improvements to module blocked on keys (#7903)
- Clarify some documentation comments - Make sure blocked-on-keys client privdata is accessible from withing the timeout callback - Handle blocked clients in beforeSleep - In case a key becomes "ready" outside of processCommand See #7879 #7880
This commit is contained in:
parent
8b497881f2
commit
addf47dcac
@ -507,7 +507,7 @@ void handleClientsBlockedOnKeys(void) {
|
||||
server.fixed_time_expire++;
|
||||
updateCachedTime(0);
|
||||
|
||||
/* Serve clients blocked on list key. */
|
||||
/* Serve clients blocked on the key. */
|
||||
robj *o = lookupKeyWrite(rl->db,rl->key);
|
||||
|
||||
if (o != NULL) {
|
||||
|
17
src/module.c
17
src/module.c
@ -4638,8 +4638,9 @@ RedisModuleBlockedClient *RM_BlockClientOnKeys(RedisModuleCtx *ctx, RedisModuleC
|
||||
|
||||
/* This function is used in order to potentially unblock a client blocked
|
||||
* on keys with RedisModule_BlockClientOnKeys(). When this function is called,
|
||||
* all the clients blocked for this key will get their reply callback called,
|
||||
* and if the callback returns REDISMODULE_OK the client will be unblocked. */
|
||||
* all the clients blocked for this key will get their reply_callback called.
|
||||
*
|
||||
* Note: The function has no effect if the signaled key doesn't exist. */
|
||||
void RM_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key) {
|
||||
signalKeyAsReady(ctx->client->db, key, OBJ_MODULE);
|
||||
}
|
||||
@ -4683,14 +4684,13 @@ int moduleClientIsBlockedOnKeys(client *c) {
|
||||
*
|
||||
* Note 1: this function can be called from threads spawned by the module.
|
||||
*
|
||||
* Note 2: when we unblock a client that is blocked for keys using
|
||||
* the API RedisModule_BlockClientOnKeys(), the privdata argument here is
|
||||
* not used, and the reply callback is called with the privdata pointer that
|
||||
* was passed when blocking the client.
|
||||
*
|
||||
* Note 2: when we unblock a client that is blocked for keys using the API
|
||||
* RedisModule_BlockClientOnKeys(), the privdata argument here is not used.
|
||||
* Unblocking a client that was blocked for keys using this API will still
|
||||
* require the client to get some reply, so the function will use the
|
||||
* "timeout" handler in order to do so. */
|
||||
* "timeout" handler in order to do so (The privdata provided in
|
||||
* RedisModule_BlockClientOnKeys() is accessible from the timeout
|
||||
* callback via RM_GetBlockedClientPrivateData). */
|
||||
int RM_UnblockClient(RedisModuleBlockedClient *bc, void *privdata) {
|
||||
if (bc->blocked_on_keys) {
|
||||
/* In theory the user should always pass the timeout handler as an
|
||||
@ -4834,6 +4834,7 @@ void moduleBlockedClientTimedOut(client *c) {
|
||||
ctx.module = bc->module;
|
||||
ctx.client = bc->client;
|
||||
ctx.blocked_client = bc;
|
||||
ctx.blocked_privdata = bc->privdata;
|
||||
bc->timeout_callback(&ctx,(void**)c->argv,c->argc);
|
||||
moduleFreeContext(&ctx);
|
||||
/* For timeout events, we do not want to call the disconnect callback,
|
||||
|
@ -2286,6 +2286,11 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
||||
* releasing the GIL. Redis main thread will not touch anything at this
|
||||
* time. */
|
||||
if (moduleCount()) moduleReleaseGIL();
|
||||
|
||||
/* Try to process blocked clients every once in while. Example: A module
|
||||
* calls RM_SignalKeyAsReady from within a timer callback (So we don't
|
||||
* visit processCommand() at all). */
|
||||
handleClientsBlockedOnKeys();
|
||||
}
|
||||
|
||||
/* This function is called immediately after the event loop multiplexing
|
||||
|
Loading…
x
Reference in New Issue
Block a user