The problem/use-case that the feature addresses Some modules might perform a long-running logic in different stages of Redis lifetime (command execution, RDB loading, ...). During this long-running logic Redis is not responsive (for example, Redis will not reply to PING commands). Lua scripts solve this problem by calling back to Redis from time to time and allowing it to process some specific commands (which are allowed while running a Lua script) and then return to the script invocation. I will like to suggest matching this capability and allowing modules to do this as well.

Description of the feature I would like to suggest a new module API that can be called while holding the Redis GIL. This API will allow Redis to take back control and reply to some special commands (like PING for example). After finishing, Redis will return the control back to the module and the module can continue running logic. I also suggest introducing a new command flag, ALLOW_BUSY, which indicates that the command can be invoked while Redis is busy (either running a Lua script or a module logic). If a command is marked with this flag, Redis will run it while in a busy mode (running Lua script or module). In addition, Redis will have the luxury to decide how to reply to other commands which are not marked with ALLOW_BUSY flag. For example, if Redis is just executing commands it will reply with -BUSY error while if it's loading an RDB it can reply with a LOADING reply. This API will match modules and Lua capabilities and will allow modules to implement their own SCRIPT KILL like mechanism.

Comment From: oranagra

LGTM

The ALLOW_BUSY flag is basically replacing this ugly list:

    if (server.lua_timedout &&
          c->cmd->proc != authCommand &&
          c->cmd->proc != helloCommand &&
          c->cmd->proc != replconfCommand &&
          c->cmd->proc != multiCommand &&
          c->cmd->proc != discardCommand &&
          c->cmd->proc != watchCommand &&
          c->cmd->proc != unwatchCommand &&
          c->cmd->proc != resetCommand &&
        !(c->cmd->proc == shutdownCommand &&
          c->argc == 2 &&
          tolower(((char*)c->argv[1]->ptr)[0]) == 'n') &&
        !(c->cmd->proc == scriptCommand &&
          c->argc == 2 &&
          tolower(((char*)c->argv[1]->ptr)[0]) == 'k'))
    {
        rejectCommand(c, shared.slowscripterr);
        return C_OK;
    }

Comment From: oranagra

@redis/core-team please comment to approve or reject that idea.

Comment From: itamarhaber

I'm happy with this.

Comment From: yossigo

LGTM, I think we can discuss the details.

Comment From: madolson

Seems reasonable to me!