From d20c6cd50cfd2fb90c61c809ad9a8b60b9443825 Mon Sep 17 00:00:00 2001 From: erhan1209 <82086267+erhan1209@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:44:14 +0300 Subject: [PATCH] Fix KEYSIZES histogram after HGETEX deletes the last hash fields `HGETEX` could delete the last remaining fields in a hash and remove the key, but still update the KEYSIZES histogram as if an empty hash still existed. That left `INFO KEYSIZES` with a stale hash entry even though the key had already been deleted. This patch makes `hgetexCommand` treat a zero-length post-operation hash as a removed key when updating the KEYSIZES histogram. Concretely, it reports the new size as `-1` for histogram accounting before deleting the key. A regression test was also added to verify that when `HGETEX PXAT 1` expires all fields in a hash, the corresponding KEYSIZES hash bucket disappears. Testing: - Added a regression test in `tests/unit/info-keysizes.tcl` covering `HGETEX` deleting the last hash fields and verifying the histogram entry is removed - Not tested --- src/t_hash.c | 6 ++++-- tests/unit/info-keysizes.tcl | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/t_hash.c b/src/t_hash.c index e258eb71f..db08ac62a 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -2914,10 +2914,12 @@ void hgetexCommand(client *c) { } /* Key may become empty due to lazy expiry in addHashFieldToReply() - * or the new expiration time is in the past.*/ + * or the new expiration time is in the past. Keep the KEYSIZES + * histogram aligned with the fact that an empty hash key is removed. */ newlen = hashTypeLength(o, 0); + int64_t hist_newlen = (newlen == 0) ? -1 : newlen; - updateKeysizesHist(c->db, OBJ_HASH, oldlen, newlen); + updateKeysizesHist(c->db, OBJ_HASH, oldlen, hist_newlen); if (newlen == 0) { dbDelete(c->db, c->argv[1]); notifyKeyspaceEvent(NOTIFY_GENERIC, "del", c->argv[1], c->db->id); diff --git a/tests/unit/info-keysizes.tcl b/tests/unit/info-keysizes.tcl index 065e3ee41..07ab2e04d 100644 --- a/tests/unit/info-keysizes.tcl +++ b/tests/unit/info-keysizes.tcl @@ -753,6 +753,12 @@ proc test_all_keysizes { {replMode 0} } { run_cmd_verify_hist {$server DEBUG RELOAD} {db0_STR:8=1} } {} {cluster:skip needs:debug} + test "KEYSIZES - HGETEX deleting the last hash fields removes the histogram entry $suffixRepl" { + run_cmd_verify_hist {$server FLUSHALL} {} + run_cmd_verify_hist {$server HSET myhash f1 v1 f2 v2 f3 v3} {db0_HASH:2=1} + run_cmd_verify_hist {$server HGETEX myhash PXAT 1 FIELDS 3 f1 f2 f3} {} + } {} {cluster:skip} + test "KEYSIZES - Test RDB $suffixRepl" { run_cmd_verify_hist {$server FLUSHALL} {} # Write list, set and zset to db0