test(redis): lock in cluster-safe single-key invariant#49
Conversation
What keeps the data-cache handler compatible with Redis Cluster / ElastiCache (cluster-mode enabled) is that it only ever issues single-key commands — Redis rejects any command spanning >1 hash slot with CROSSSLOT. Add a test that records every command across the full handler surface (both the tag-driven and TTL-driven deletion paths) and asserts none targets more than one key, so a future multi-key change (e.g. del(k1, k2), mget) can't silently break cluster users. The test is non-vacuous — it asserts the del paths actually ran. Also document the guarantee in docs/redis.md and clarify cluster-mode-disabled vs -enabled ElastiCache (the former is single-node-equivalent; the latter uses the ioredis Cluster client — slot-safe either way). No live multi-node cluster CI: it would mostly exercise ioredis (not this library), is a known source of CI flake, and would risk wedging the auto-merge release gate for coverage a unit-tested invariant provides for free. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request adds documentation and a test suite to ensure and explain Redis Cluster safety, verifying that the handler only issues single-key commands to prevent CROSSSLOT errors. The feedback suggests making the new test more robust by asserting the exact keys that are deleted rather than just checking if any deletion occurred.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| // Both deletion paths must have run (otherwise the assertion is vacuous)... | ||
| expect(commands.some((c) => c.method === "del")).toBe(true); |
There was a problem hiding this comment.
While asserting that del was called is a good sanity check, we can make this test significantly more robust and precise by asserting the exact keys that were deleted (nextjs:data-cache:k1 and nextjs:data-cache:k2). This ensures that the correct keys are targeted for deletion and prevents false positives where del might be called with unexpected keys.
// Both deletion paths must have run (otherwise the assertion is vacuous)...
const delCommands = commands.filter((c) => c.method === "del");
expect(delCommands).toEqual([
{ method: "del", keys: ["nextjs:data-cache:k1"] },
{ method: "del", keys: ["nextjs:data-cache:k2"] }
]);
Why
The data-cache handler is compatible with Redis Cluster / ElastiCache (cluster-mode enabled) purely because it only ever issues single-key commands — Redis rejects any command spanning more than one hash slot with
CROSSSLOT. That's an invariant worth guarding.What
redis.test.ts→ "only ever issues single-key commands"): records every command the handler issues across its full surface — including both the tag-driven and TTL-driven deletion paths — and asserts none targets >1 key. Non-vacuous: it also asserts thedelpaths actually executed, so it fails loudly the day someone adds adel(k1, k2)/mget/ multi-key transaction.docs/redis.md): document the slot-safety guarantee, and clarify cluster-mode-disabled (single-node-equivalent) vs cluster-mode-enabled (ioredisClusterclient) ElastiCache.Why not a live cluster CI job
Considered it, decided against:
🤖 Generated with Claude Code