You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SubscriptionManager.unsubscribe cleans up the subscription dict, sid map, and pushes a sentinel — but it does NOT call OrderbookManager.remove(ticker). There is also no public unsubscribe path on KalshiWebSocket itself that wires orderbook teardown.
A long-running run_forever that periodically rotates orderbook subscriptions (common for market-makers cycling through contract expirations) accumulates _BookState entries for every ticker ever subscribed. Per-ticker memory is small but grows unbounded over weeks of uptime; more importantly, the stale books are still served by OrderbookManager.get() if any caller looks them up — silently returning stale data.
Only _handle_seq_gap and _handle_reconnect call _orderbook_mgr.remove / .clear() — neither is the unsubscribe path.
Add an orderbook-aware unsubscribe path on KalshiWebSocket that:
Looks up sub.params.get('market_tickers', []) for the subscription about to be removed.
Calls self._orderbook_mgr.remove(ticker) for each ticker before delegating to SubscriptionManager.unsubscribe.
For all-markets orderbook subscriptions (no market_tickers param), tracks which tickers a sid produced snapshots for in OrderbookManager state, then removes all of them.
Same cleanup must run on _handle_server_unsubscribe in dispatch.py (server-initiated unsubscribe) — verify it does, or wire it.
Activity
fix(ws): orderbook resync; seq reset detection; permanent close codes…