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 *
| 5390 | * |
| 5391 | */ |
| 5392 | 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) { |
| 5393 | client *c = ctx->client; |
| 5394 | int islua = serverTL->in_eval; |
| 5395 | int ismulti = serverTL->in_exec; |
| 5396 | |
| 5397 | c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient)); |
| 5398 | RedisModuleBlockedClient *bc = (RedisModuleBlockedClient*)c->bpop.module_blocked_handle; |
| 5399 | ctx->module->blocked_clients++; |
| 5400 | |
| 5401 | /* We need to handle the invalid operation of calling modules blocking |
| 5402 | * commands from Lua or MULTI. We actually create an already aborted |
| 5403 | * (client set to NULL) blocked client handle, and actually reply with |
| 5404 | * an error. */ |
| 5405 | mstime_t timeout = timeout_ms ? (mstime()+timeout_ms) : 0; |
| 5406 | bc->client = (islua || ismulti) ? NULL : c; |
| 5407 | bc->module = ctx->module; |
| 5408 | bc->reply_callback = reply_callback; |
| 5409 | bc->timeout_callback = timeout_callback; |
| 5410 | bc->disconnect_callback = NULL; /* Set by RM_SetDisconnectCallback() */ |
| 5411 | bc->free_privdata = free_privdata; |
| 5412 | bc->privdata = privdata; |
| 5413 | bc->reply_client = createClient(NULL, IDX_EVENT_LOOP_MAIN); |
| 5414 | bc->reply_client->flags |= CLIENT_MODULE; |
| 5415 | bc->dbid = c->db->id; |
| 5416 | bc->blocked_on_keys = keys != NULL; |
| 5417 | bc->unblocked = 0; |
| 5418 | bc->background_timer = 0; |
| 5419 | bc->background_duration = 0; |
| 5420 | c->bpop.timeout = timeout; |
| 5421 | |
| 5422 | if (islua || ismulti) { |
| 5423 | c->bpop.module_blocked_handle = NULL; |
| 5424 | addReplyError(c, islua ? |
| 5425 | "Blocking module command called from Lua script" : |
| 5426 | "Blocking module command called from transaction"); |
| 5427 | } else { |
| 5428 | if (keys) { |
| 5429 | blockForKeys(c,BLOCKED_MODULE,keys,numkeys,timeout,NULL,NULL,NULL); |
| 5430 | } else { |
| 5431 | blockClient(c,BLOCKED_MODULE); |
| 5432 | } |
| 5433 | } |
| 5434 | return bc; |
| 5435 | } |
| 5436 | |
| 5437 | /* This function is called from module.c in order to check if a module |
| 5438 | * blocked for BLOCKED_MODULE and subtype 'on keys' (bc->blocked_on_keys true) |
no test coverage detected