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++;
|
server.fixed_time_expire++;
|
||||||
updateCachedTime(0);
|
updateCachedTime(0);
|
||||||
|
|
||||||
/* Serve clients blocked on list key. */
|
/* Serve clients blocked on the key. */
|
||||||
robj *o = lookupKeyWrite(rl->db,rl->key);
|
robj *o = lookupKeyWrite(rl->db,rl->key);
|
||||||
|
|
||||||
if (o != NULL) {
|
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
|
/* This function is used in order to potentially unblock a client blocked
|
||||||
* on keys with RedisModule_BlockClientOnKeys(). When this function is called,
|
* on keys with RedisModule_BlockClientOnKeys(). When this function is called,
|
||||||
* all the clients blocked for this key will get their reply callback 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. */
|
*
|
||||||
|
* Note: The function has no effect if the signaled key doesn't exist. */
|
||||||
void RM_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key) {
|
void RM_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key) {
|
||||||
signalKeyAsReady(ctx->client->db, key, OBJ_MODULE);
|
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 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
|
* Note 2: when we unblock a client that is blocked for keys using the API
|
||||||
* the API RedisModule_BlockClientOnKeys(), the privdata argument here is
|
* RedisModule_BlockClientOnKeys(), the privdata argument here is not used.
|
||||||
* not used, and the reply callback is called with the privdata pointer that
|
|
||||||
* was passed when blocking the client.
|
|
||||||
*
|
|
||||||
* Unblocking a client that was blocked for keys using this API will still
|
* 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
|
* 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) {
|
int RM_UnblockClient(RedisModuleBlockedClient *bc, void *privdata) {
|
||||||
if (bc->blocked_on_keys) {
|
if (bc->blocked_on_keys) {
|
||||||
/* In theory the user should always pass the timeout handler as an
|
/* 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.module = bc->module;
|
||||||
ctx.client = bc->client;
|
ctx.client = bc->client;
|
||||||
ctx.blocked_client = bc;
|
ctx.blocked_client = bc;
|
||||||
|
ctx.blocked_privdata = bc->privdata;
|
||||||
bc->timeout_callback(&ctx,(void**)c->argv,c->argc);
|
bc->timeout_callback(&ctx,(void**)c->argv,c->argc);
|
||||||
moduleFreeContext(&ctx);
|
moduleFreeContext(&ctx);
|
||||||
/* For timeout events, we do not want to call the disconnect callback,
|
/* 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
|
* releasing the GIL. Redis main thread will not touch anything at this
|
||||||
* time. */
|
* time. */
|
||||||
if (moduleCount()) moduleReleaseGIL();
|
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
|
/* This function is called immediately after the event loop multiplexing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user