mirror of
https://github.com/redis/redis.git
synced 2026-04-22 19:37:30 -04:00
**Summary** Ensures `db->stream_idmp_keys` is managed consistently with `keys`, `expires`, and `subexpires` across every database lifecycle operation — flush, swap, temp-DB init/discard, lazy-free, and cluster slot migration. Without this fix, the dict was absent from these code paths, causing three classes of bugs: a SIGSEGV during diskless replication in `swapdb` mode (NULL pointer dereference in `initTempDb`), silently lost IDMP tracking after `SWAPDB` and diskless replication (pointers never swapped), and stale IDMP entries surviving `FLUSHDB` (dict never cleared). **Changes** - **`emptyDbStructure`** (`src/db.c`) — Clear `stream_idmp_keys` on flush so stale entries don't persist across `FLUSHDB`/`FLUSHALL`. - **`initTempDb` / `discardTempDb`** (`src/db.c`) — Create and release `stream_idmp_keys` for temp databases used during diskless replication RDB load. Fixes the SIGSEGV when `rdbLoadRioWithLoadingCtx` calls `dictAddRaw` on a NULL pointer. - **`dbSwapDatabases`** (`src/db.c`) — Swap `stream_idmp_keys` alongside the other per-DB dicts so IDMP tracking follows the data during `SWAPDB`. - **`swapMainDbWithTempDb`** (`src/db.c`) — Swap `stream_idmp_keys` when promoting a temp database after diskless replication, so the cron can discover and expire IDMP entries on replicas. - **`streamMoveIdmpKeys`** (`src/db.c`) — New helper that migrates IDMP entries by slot from one dict to another, used during cluster slot migration. - **`emptyDbAsync` / `emptyDbDataAsync`** (`src/lazyfree.c`) — Replace the dict with a fresh one and hand the old one to the background lazy-free job. - **`lazyfreeFreeDatabase`** (`src/lazyfree.c`) — Free `stream_idmp_keys` in the background job (now takes 4 args instead of 3). - **`asmTriggerBackgroundTrim`** (`src/cluster_asm.c`) — Move matching IDMP entries by slot into a temporary dict during background trim, then pass it to `emptyDbDataAsync` for async cleanup. - **`server.h`** — Updated `emptyDbDataAsync` signature; added `streamMoveIdmpKeys` declaration. - **Tests** (`tests/unit/type/stream.tcl`) — Four new integration tests covering IDMP expiry after `SAVE` + restart, tracking survival across `SWAPDB`, cleanup on `FLUSHDB`, and diskless replication in `swapdb` mode (both `rdbchannel=yes` and `rdbchannel=no`). **What this fixes** - **No crash on diskless replication** — `initTempDb` now initializes the dict, eliminating the NULL dereference during RDB load. - **Tracking preserved across swaps** — Both `SWAPDB` and diskless replication correctly transfer the dict, so the cron keeps expiring entries in the right database. - **Clean state after flush** — `FLUSHDB`/`FLUSHALL` clear the dict, preventing ghost entries from interfering with new streams. - **Correct cluster migration cleanup** — IDMP entries for migrated slots are moved and freed alongside the key data.