Skip to content

Commit 15ae145

Browse files
chrisguidryclaude
andcommitted
Fix Redis Cluster CROSSSLOT error in debounce Lua script
The debounce Lua script uses two keys (winner + last_seen) that need to land on the same cluster slot. Added a hash tag so Redis routes them together. Also fixed the multiple-cooldowns test to not depend on execution order. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 88eece7 commit 15ae145

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

src/docket/dependencies/_debounce.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,15 @@ async def __aenter__(self) -> Debounce:
113113

114114
scope = self.scope or docket.name
115115
if self._argument_name is not None:
116-
base_key = f"{scope}:debounce:{self._argument_name}:{self._argument_value}"
116+
hash_tag = f"{self._argument_name}:{self._argument_value}"
117+
base_key = f"{scope}:debounce:{hash_tag}"
117118
else:
118-
base_key = f"{scope}:debounce:{execution.function_name}"
119+
hash_tag = execution.function_name
120+
base_key = f"{scope}:debounce:{hash_tag}"
119121

120-
winner_key = f"{base_key}:winner"
121-
seen_key = f"{base_key}:last_seen"
122+
# Use a Redis hash tag {…} so both keys land on the same cluster slot
123+
winner_key = f"{base_key}:{{{hash_tag}}}:winner"
124+
seen_key = f"{base_key}:{{{hash_tag}}}:last_seen"
122125

123126
settle_ms = int(self.settle.total_seconds() * 1000)
124127
now_ms = int(time.time() * 1000)

tests/test_cooldown.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,15 @@ async def task(
8282
results.append((customer_id, region))
8383

8484
await docket.add(task)(customer_id=1, region="us")
85+
await worker.run_until_finished()
86+
8587
await docket.add(task)(
8688
customer_id=1, region="eu"
8789
) # same customer, different region
8890
await docket.add(task)(
8991
customer_id=2, region="us"
9092
) # different customer, same region
9193

92-
worker.concurrency = 10
9394
await worker.run_until_finished()
9495

9596
# First call runs. Second is blocked by customer_id=1. Third is blocked by region="us".

0 commit comments

Comments
 (0)