Commit 303ebe2
authored
fix(redis): bound BZPOPMIN fast mode to redisBlockWaitFallback (#683)
Address Codex P1 / Claude bot review on 6173f58:
The previous bzpopminWaitLoop set `fast` directly from
waitForBlockedCommandUpdate's return value. Under sustained
zsetWaiters.Signal pressure (a ZADD/ZINCRBY hot key whose signals fire
faster than each bzpopminTryAllKeys round finishes) the buffered-1
waiterC stays perpetually full: every wait returns via the signal arm,
fast stays true forever, the 100 ms fallback timer never fires. A
wrongType write (HSET / SET / etc.) on a co- registered key (multi-key
BZPOPMIN) then goes undetected for the entire BLOCK window — a
regression vs #666's strict 100 ms ceiling.
Fix: track the wall time of the last full check inside bzpopminWaitLoop
and demote `fast` back to false once redisBlockWaitFallback has elapsed
since that check. Signal-driven wakes still take the fast path during
the first 100 ms after a full check; after that, the next wake (signal
or timer) runs the full check and resets the budget. The 100 ms
WRONGTYPE-detection ceiling is restored regardless of signal rate.
Per CLAUDE.md regression-test convention, the failing scenario is locked
down by TestRedis_BZPopMinDetectsWrongTypeUnderSignalLoad before the
fix:
- A signal-pressure goroutine drives zsetWaiters.Signal in a tight loop
on bzpop-press-hot. The reader's waiter, registered on both
bzpop-press-cold and bzpop-press-hot, wakes on every signal.
- After the reader settles into fast mode (~200 ms), a string is SET at
bzpop-press-cold.
- Pre-fix: the loop never demotes fast=false, the fast-path probe on
bzpop-press-cold never detects the wrongType, BZPOPMIN times out at the
3 s BLOCK deadline.
- Post-fix: the wall-time gate forces a full check within ~100 ms of the
SET, WRONGTYPE surfaces well before the BLOCK deadline.
Verified: the test fails on parent commit 6173f58 (loop ran for the
full 3 s without surfacing WRONGTYPE) and passes on this commit (returns
WRONGTYPE in ~100 ms).
Drive-by cleanups from the same review pass:
- Collapse tryBZPopMin / tryBZPopMinFast wrappers; bzpopminTryAllKeys
calls tryBZPopMinWithMode directly with the fast bool. Both wrappers had
no other callers (per grep) and only added one level of indirection.
- Move TestRedis_BZPopMinTimesOutOnEmptyKey's stranded doc comment back
over its own function; the previous PR mistakenly prepended it to
TestRedis_BZPopMinRejectsInitialWrongType.
Self-review (CLAUDE.md 5 lenses):
1. Data loss -- None. Loop control flow only; persistBZPopMinResult path
unchanged.
2. Concurrency -- The wall-time gate is a local variable; no shared
state added. waitForBlockedCommandUpdate's signaled-bool contract is
unchanged.
3. Performance -- One time.Since per loop iteration on top of the
existing ScanAt cost; negligible. Worst-case fast-path utilisation drops
from "always" to "first 100 ms of every full check window," but the
fast-mode CPU win is still claimed for the dominant signal-driven case
(most BZPOPMIN BLOCK windows complete within one full-check window
because the consumer pops the first matched ZADD).
4. Data consistency -- WRONGTYPE detection ceiling is back to 100 ms
regardless of signal rate. Fast-path correctness invariants from #677
(signal-driven wake guarantees no wrongType transition) are unchanged.
5. Test coverage -- regression-test-first per CLAUDE.md convention.
Existing TestRedis_BZPopMinRejectsInitialWrongType,
TestRedis_BZPopMinDetectsMidBlockWrongType, and
TestRedis_BZPopMinTimesOutOnEmptyKey continue to lock down the other
branches.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* BZPOPMIN now correctly detects wrong-type errors even under sustained
signal-driven conditions, preventing timeouts in edge cases
* **Tests**
* Added test to verify BZPOPMIN wrong-type error detection under high
signal load
<!-- end of auto-generated comment: release notes by coderabbit.ai -->2 files changed
Lines changed: 134 additions & 46 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
113 | 114 | | |
114 | 115 | | |
115 | 116 | | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | 117 | | |
123 | 118 | | |
124 | 119 | | |
| |||
195 | 190 | | |
196 | 191 | | |
197 | 192 | | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
198 | 286 | | |
199 | 287 | | |
200 | 288 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3650 | 3650 | | |
3651 | 3651 | | |
3652 | 3652 | | |
3653 | | - | |
3654 | | - | |
3655 | | - | |
3656 | | - | |
3657 | | - | |
3658 | | - | |
3659 | | - | |
3660 | | - | |
3661 | | - | |
3662 | | - | |
3663 | | - | |
3664 | | - | |
3665 | | - | |
3666 | | - | |
3667 | | - | |
3668 | | - | |
3669 | | - | |
| 3653 | + | |
| 3654 | + | |
| 3655 | + | |
| 3656 | + | |
| 3657 | + | |
| 3658 | + | |
| 3659 | + | |
3670 | 3660 | | |
3671 | 3661 | | |
3672 | 3662 | | |
| |||
3786 | 3776 | | |
3787 | 3777 | | |
3788 | 3778 | | |
3789 | | - | |
3790 | | - | |
3791 | | - | |
3792 | | - | |
3793 | | - | |
3794 | | - | |
3795 | | - | |
3796 | | - | |
3797 | | - | |
3798 | | - | |
| 3779 | + | |
| 3780 | + | |
| 3781 | + | |
| 3782 | + | |
| 3783 | + | |
| 3784 | + | |
| 3785 | + | |
| 3786 | + | |
| 3787 | + | |
| 3788 | + | |
| 3789 | + | |
| 3790 | + | |
| 3791 | + | |
| 3792 | + | |
| 3793 | + | |
| 3794 | + | |
| 3795 | + | |
| 3796 | + | |
| 3797 | + | |
| 3798 | + | |
3799 | 3799 | | |
| 3800 | + | |
3800 | 3801 | | |
3801 | 3802 | | |
3802 | 3803 | | |
| |||
3805 | 3806 | | |
3806 | 3807 | | |
3807 | 3808 | | |
| 3809 | + | |
| 3810 | + | |
| 3811 | + | |
3808 | 3812 | | |
3809 | 3813 | | |
3810 | 3814 | | |
3811 | 3815 | | |
3812 | | - | |
| 3816 | + | |
| 3817 | + | |
3813 | 3818 | | |
3814 | 3819 | | |
3815 | 3820 | | |
3816 | | - | |
3817 | | - | |
3818 | | - | |
3819 | | - | |
3820 | | - | |
| 3821 | + | |
| 3822 | + | |
| 3823 | + | |
| 3824 | + | |
| 3825 | + | |
| 3826 | + | |
3821 | 3827 | | |
3822 | 3828 | | |
3823 | | - | |
3824 | | - | |
3825 | | - | |
3826 | | - | |
3827 | | - | |
3828 | | - | |
3829 | | - | |
| 3829 | + | |
3830 | 3830 | | |
3831 | 3831 | | |
3832 | 3832 | | |
| |||
0 commit comments