diff --git a/src/blocked.c b/src/blocked.c index a7548ce98..fc2b5cdc6 100644 --- a/src/blocked.c +++ b/src/blocked.c @@ -325,6 +325,9 @@ void handleClientsBlockedOnKeys(void) { * (i.e. not from call(), module context, etc.) */ serverAssert(server.also_propagate.numops == 0); + /* If a command being unblocked causes another command to get unblocked, + * like a BLMOVE would do, then the new unblocked command will get processed + * right away rather than wait for later. */ while(listLength(server.ready_keys) != 0) { list *l; diff --git a/tests/unit/type/list.tcl b/tests/unit/type/list.tcl index a57e5df3e..993b6d135 100644 --- a/tests/unit/type/list.tcl +++ b/tests/unit/type/list.tcl @@ -2312,4 +2312,52 @@ foreach {pop} {BLPOP BLMPOP_RIGHT} { $rd close } + + test {Command being unblocked cause another command to get unblocked execution order test} { + r del src{t} dst{t} key1{t} key2{t} key3{t} + set repl [attach_to_replication_stream] + + set rd1 [redis_deferring_client] + set rd2 [redis_deferring_client] + set rd3 [redis_deferring_client] + + $rd1 blmove src{t} dst{t} left right 0 + wait_for_blocked_clients_count 1 + + $rd2 blmove dst{t} src{t} right left 0 + wait_for_blocked_clients_count 2 + + # Create a pipeline of commands that will be processed in one socket read. + # Insert two set commands before and after lpush to observe the execution order. + set buf "" + append buf "set key1{t} value1\r\n" + append buf "lpush src{t} dummy\r\n" + append buf "set key2{t} value2\r\n" + $rd3 write $buf + $rd3 flush + + wait_for_blocked_clients_count 0 + + r set key3{t} value3 + + # If a command being unblocked causes another command to get unblocked, like a BLMOVE would do, + # then the new unblocked command will get processed right away rather than wait for later. + # If the set command occurs between two lmove commands, the results are not as expected. + assert_replication_stream $repl { + {select *} + {set key1{t} value1} + {lpush src{t} dummy} + {lmove src{t} dst{t} left right} + {lmove dst{t} src{t} right left} + {set key2{t} value2} + {set key3{t} value3} + } + + $rd1 close + $rd2 close + $rd3 close + + close_replication_stream $repl + } {} {needs:repl} + } ;# stop servers