• guybe7's avatar
    Fix some issues with modules and MULTI/EXEC (#8617) · 3d0b427c
    guybe7 authored
    Bug 1:
    When a module ctx is freed moduleHandlePropagationAfterCommandCallback
    is called and handles propagation. We want to prevent it from propagating
    commands that were not replicated by the same context. Example:
    1. module1.foo does: RM_Replicate(cmd1); RM_Call(cmd2); RM_Replicate(cmd3)
    2. RM_Replicate(cmd1) propagates MULTI and adds cmd1 to also_propagagte
    3. RM_Call(cmd2) create a new ctx, calls call() and destroys the ctx.
    4. moduleHandlePropagationAfterCommandCallback is called, calling
       alsoPropagates EXEC (Note: EXEC is still not written to socket),
       setting server.in_trnsaction = 0
    5. RM_Replicate(cmd3) is called, propagagting yet another MULTI (now
       we have nested MULTI calls, which is no good) and then cmd3
    
    We must prevent RM_Call(cmd2) from resetting server.in_transaction.
    REDISMODULE_CTX_MULTI_EMITTED was revived for that purpose.
    
    Bug 2:
    Fix issues with nested RM_Call where some have '!' and some don't.
    Example:
    1. module1.foo does RM_Call of module2.bar without replication (i.e. no '!')
    2. module2.bar internally calls RM_Call of INCR with '!'
    3. at the end of module1.foo we call RM_ReplicateVerbatim
    
    We want the replica/AOF to see only module1.foo and not the INCR from module2.bar
    
    Introduced a global replication_allowed flag inside RM_Call to determine
    whether we need to replicate or not (even if '!' was specified)
    
    Other changes:
    Split beforePropagateMultiOrExec to beforePropagateMulti afterPropagateExec
    just for better readability
    3d0b427c
multi.c 14.6 KB