Commit 70f4e44
Check single-subscription channels before queueing, not during replay
`userEvents` and `orderUpdates` cannot be multiplexed, and `subscribe` rejects a
second one with `NotImplementedError`. That check only ran on the connected
path, so subscribing twice before the socket opened was accepted, queued, and
only rejected later while `on_open` replayed the queue.
The exception then escapes inside the websocket callback, where the caller
cannot catch it, and it aborts the replay loop. Every subscription queued behind
the duplicate is silently dropped:
ws_manager.subscribe({"type": "userEvents"}, cb) # queued
ws_manager.subscribe({"type": "userEvents"}, cb) # queued, no error
ws_manager.subscribe({"type": "l2Book", "coin": "ETH"}, cb)
# on_open -> NotImplementedError on the second entry
# frames sent to the server: 1
# l2Book:eth registered: False
The same two calls after the socket is open raise at the call site, so identical
user code either raises where it is written or loses an unrelated market data
feed, depending only on connection timing.
Run the check in `subscribe` for both paths, counting queued entries as well as
active ones, so the duplicate is refused where it is requested. `on_open` now
takes the queue before replaying it: `subscribe` consults that list, and leaving
entries in place would also replay them again on a later `on_open`.
Behaviour on the connected path is unchanged, and channels that do multiplex
still accept several callbacks.
Tests: `tests/websocket_manager_test.py` covers the duplicate on both paths, the
dropped-subscription case, queue replay and clearing, and multiplexing. Against
the unmodified file three of the five fail; the two that pass either way are the
connected-path duplicate and the multiplexing case.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 2fdb18f commit 70f4e44
2 files changed
Lines changed: 90 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
130 | | - | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
131 | 135 | | |
132 | 136 | | |
133 | 137 | | |
| |||
136 | 140 | | |
137 | 141 | | |
138 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
139 | 151 | | |
140 | 152 | | |
141 | 153 | | |
142 | 154 | | |
143 | 155 | | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | 156 | | |
150 | 157 | | |
151 | 158 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
0 commit comments