Block a client in the context of a module: this function implements both * RM_BlockClient() and RM_BlockClientOnKeys() depending on the fact the * keys are passed or not. * * When not blocking for keys, the keys, numkeys, and privdata parameters are * not needed. The privdata in that case must be NULL, since later is * RM_UnblockClient() that will provide some private data that the reply *
| 5281 | * |
| 5282 | */ |
| 5283 | RedisModuleBlockedClient *moduleBlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata) { |
| 5284 | client *c = ctx->client; |
| 5285 | int islua = server.in_eval; |
| 5286 | int ismulti = server.in_exec; |
| 5287 | |
| 5288 | c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient)); |
| 5289 | RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle; |
| 5290 | ctx->module->blocked_clients++; |
| 5291 | |
| 5292 | /* We need to handle the invalid operation of calling modules blocking |
| 5293 | * commands from Lua or MULTI. We actually create an already aborted |
| 5294 | * (client set to NULL) blocked client handle, and actually reply with |
| 5295 | * an error. */ |
| 5296 | mstime_t timeout = timeout_ms ? (mstime()+timeout_ms) : 0; |
| 5297 | bc->client = (islua || ismulti) ? NULL : c; |
| 5298 | bc->module = ctx->module; |
| 5299 | bc->reply_callback = reply_callback; |
| 5300 | bc->timeout_callback = timeout_callback; |
| 5301 | bc->disconnect_callback = NULL; /* Set by RM_SetDisconnectCallback() */ |
| 5302 | bc->free_privdata = free_privdata; |
| 5303 | bc->privdata = privdata; |
| 5304 | bc->reply_client = createClient(NULL); |
| 5305 | bc->reply_client->flags |= CLIENT_MODULE; |
| 5306 | bc->dbid = c->db->id; |
| 5307 | bc->blocked_on_keys = keys != NULL; |
| 5308 | bc->unblocked = 0; |
| 5309 | bc->background_timer = 0; |
| 5310 | bc->background_duration = 0; |
| 5311 | c->bpop.timeout = timeout; |
| 5312 | |
| 5313 | if (islua || ismulti) { |
| 5314 | c->bpop.module_blocked_handle = NULL; |
| 5315 | addReplyError(c, islua ? |
| 5316 | "Blocking module command called from Lua script" : |
| 5317 | "Blocking module command called from transaction"); |
| 5318 | } else { |
| 5319 | if (keys) { |
| 5320 | blockForKeys(c,BLOCKED_MODULE,keys,numkeys,timeout,NULL,NULL,NULL); |
| 5321 | } else { |
| 5322 | blockClient(c,BLOCKED_MODULE); |
| 5323 | } |
| 5324 | } |
| 5325 | return bc; |
| 5326 | } |
| 5327 | |
| 5328 | /* This function is called from module.c in order to check if a module |
| 5329 | * blocked for BLOCKED_MODULE and subtype 'on keys' (bc->blocked_on_keys true) |
no test coverage detected