From #106 F-P-15 (Wave 5 polish backlog). Severity: low (defense-in-depth, no observed regression).
Current behavior
kalshi/ws/backpressure.py — MessageQueue uses a collections.deque with manual size tracking via a counter updated on put / get / DROP_OLDEST eviction. The counter is the sole bound on memory; if a future bug breaks the counter (e.g. a put path that forgets to increment, an exception between deque-append and counter-update) the deque can grow without bound.
The O(1) qsize() work from #103 already relies on this counter for correctness — a single drift point bounds both queue size and memory.
Fix
Construct the underlying deque with a hard ceiling:
self._buffer: deque[T] = deque(maxlen=maxsize + 1)
The maxlen is enforced by deque itself — independent of the counter. +1 is the safety margin so the manual DROP_OLDEST / RAISE logic still gets to observe the overflow boundary one slot before deque silently evicts.
Tests
- Existing
tests/ws/test_backpressure.py should continue to pass unchanged (the maxlen is loose enough to never trigger in correct operation).
- Add a regression test that injects a corrupted counter state (
q._size = 0 after multiple puts) and asserts the deque cannot exceed maxsize + 1 regardless.
Acceptance
- One-line change in
kalshi/ws/backpressure.py.
- New regression test covering counter-drift safety.
- No behavior change in passing path;
tests/ws/test_backpressure.py green unchanged.
From #106 F-P-15 (Wave 5 polish backlog). Severity: low (defense-in-depth, no observed regression).
Current behavior
kalshi/ws/backpressure.py—MessageQueueuses acollections.dequewith manual size tracking via a counter updated onput/get/DROP_OLDESTeviction. The counter is the sole bound on memory; if a future bug breaks the counter (e.g. a put path that forgets to increment, an exception between deque-append and counter-update) the deque can grow without bound.The O(1)
qsize()work from #103 already relies on this counter for correctness — a single drift point bounds both queue size and memory.Fix
Construct the underlying deque with a hard ceiling:
The
maxlenis enforced by deque itself — independent of the counter.+1is the safety margin so the manualDROP_OLDEST/RAISElogic still gets to observe the overflow boundary one slot before deque silently evicts.Tests
tests/ws/test_backpressure.pyshould continue to pass unchanged (the maxlen is loose enough to never trigger in correct operation).q._size = 0after multiple puts) and asserts the deque cannot exceedmaxsize + 1regardless.Acceptance
kalshi/ws/backpressure.py.tests/ws/test_backpressure.pygreen unchanged.