diff --git a/src/networking.c b/src/networking.c index 339cd304d4..48e397e6f4 100644 --- a/src/networking.c +++ b/src/networking.c @@ -4520,6 +4520,16 @@ void flushReplicasOutputBuffers(void) { } } +mstime_t getPausedActionTimeout(uint32_t action) { + mstime_t timeout = 0; + for (int i = 0; i < NUM_PAUSE_PURPOSES; i++) { + pause_event *p = &(server.client_pause_per_purpose[i]); + if (p->paused_actions & action && (p->end - server.mstime) > timeout) + timeout = p->end - server.mstime; + } + return timeout; +} + /* Compute current paused actions and its end time, aggregated for * all pause purposes. */ void updatePausedActions(void) { diff --git a/src/server.c b/src/server.c index b5389c62b5..8255b57e25 100644 --- a/src/server.c +++ b/src/server.c @@ -5668,6 +5668,17 @@ sds genValkeyInfoString(dict *section_dict, int all_sections, int everything) { unsigned long blocking_keys, blocking_keys_on_nokey, watched_keys; getExpansiveClientsInfo(&maxin, &maxout); totalNumberOfStatefulKeys(&blocking_keys, &blocking_keys_on_nokey, &watched_keys); + + char *paused_actions = "none"; + long long paused_timeout = 0; + if (server.paused_actions & PAUSE_ACTION_CLIENT_ALL) { + paused_actions = "all"; + paused_timeout = getPausedActionTimeout(PAUSE_ACTION_CLIENT_ALL); + } else if (server.paused_actions & PAUSE_ACTION_CLIENT_WRITE) { + paused_actions = "write"; + paused_timeout = getPausedActionTimeout(PAUSE_ACTION_CLIENT_WRITE); + } + if (sections++) info = sdscat(info, "\r\n"); info = sdscatprintf( info, @@ -5684,7 +5695,9 @@ sds genValkeyInfoString(dict *section_dict, int all_sections, int everything) { "clients_in_timeout_table:%llu\r\n", (unsigned long long)raxSize(server.clients_timeout_table), "total_watched_keys:%lu\r\n", watched_keys, "total_blocking_keys:%lu\r\n", blocking_keys, - "total_blocking_keys_on_nokey:%lu\r\n", blocking_keys_on_nokey)); + "total_blocking_keys_on_nokey:%lu\r\n", blocking_keys_on_nokey, + "paused_actions:%s\r\n", paused_actions, + "paused_timeout_milliseconds:%lld\r\n", paused_timeout)); } /* Memory */ diff --git a/src/server.h b/src/server.h index 0725c6a880..d186d16c73 100644 --- a/src/server.h +++ b/src/server.h @@ -2714,6 +2714,7 @@ void pauseActions(pause_purpose purpose, mstime_t end, uint32_t actions); void unpauseActions(pause_purpose purpose); uint32_t isPausedActions(uint32_t action_bitmask); uint32_t isPausedActionsWithUpdate(uint32_t action_bitmask); +mstime_t getPausedActionTimeout(uint32_t action); void updatePausedActions(void); void unblockPostponedClients(void); void processEventsWhileBlocked(void); diff --git a/tests/unit/pause.tcl b/tests/unit/pause.tcl index b18a32d48f..9697c3b44e 100644 --- a/tests/unit/pause.tcl +++ b/tests/unit/pause.tcl @@ -1,4 +1,23 @@ start_server {tags {"pause network"}} { + test "Test check paused_actions in info stats" { + assert_equal [s paused_actions] "none" + assert_equal [s paused_timeout_milliseconds] 0 + + r client PAUSE 10000 WRITE + assert_equal [s paused_actions] "write" + after 1000 + set timeout [s paused_timeout_milliseconds] + assert {$timeout > 0 && $timeout < 9000} + r client unpause + + r multi + r client PAUSE 1000 ALL + r info clients + assert_match "*paused_actions:all*" [r exec] + + r client unpause + } + test "Test read commands are not blocked by client pause" { r client PAUSE 100000 WRITE set rd [valkey_deferring_client]