Skip to content

perf(ws): inplace orderbook updates; config knobs; pluggable JSON; small polish - #232

Merged
TexasCoding merged 1 commit into
mainfrom
audit/w2a-ws-perf-config
May 21, 2026
Merged

TexasCoding merged 1 commit into
mainfrom
audit/w2a-ws-perf-config

Conversation

@TexasCoding

Copy link
Copy Markdown
Owner

Wave 2-A of audit umbrella. Three issues + 3 P2 polish items.

Changes

Closes #199, Closes #208, Closes #209
Refs #221 (W2-C lands items 3/4)
Refs #224

…all polish

- OrderbookManager: split state mutation from materialization. Recv loop now uses _apply_*_inplace variants — stops building+discarding ~2N OrderbookLevel allocations per frame on deep books.

- KalshiConfig: new ws_ping_interval, ws_close_timeout, ws_json_loads, ws_json_dumps fields.

- ConnectionManager.connect/reconnect deduped via _open_socket helper; uses Full Jitter formula matching REST.

- OrderbookDeltaPayload.side typed as Literal['yes','no'] — invalid sides now rejected at parse.

- MessageQueue.put_sentinel is a no-op when already closed.

Closes #199, Closes #208, Closes #209

Refs #221 (P2 items 1/2/5 — W2-C finishes items 3/4: populate_by_name + AwareDatetime)

Refs #224
@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review — PR #232

Well-structured PR with a clear scope per issue. The audit trail (issue refs in code comments) is especially useful. Below are findings grouped by severity.


Findings

1. Dead branch in apply_delta wrapper (kalshi/ws/orderbook.py)

def apply_delta(self, msg: OrderbookDeltaMessage) -> Orderbook | None:
    if not self._apply_delta_inplace(msg):
        return None
    state = self._books.get(msg.msg.market_ticker)   # <-- get() can't return None here
    return state.to_orderbook() if state else None    # <-- `else None` is dead code

After _apply_delta_inplace returns True, the ticker is guaranteed to be in self._books — there is no await between the mutation and the lookup so no other coroutine can remove it. The if state else None guard is dead code that silently eats an invariant violation instead of surfacing it. Either use self._books[ticker] (which will raise on a broken invariant) or add an assertion:

state = self._books[msg.msg.market_ticker]  # KeyError = broken invariant, not silent None
return state.to_orderbook()

2. ws_json_dumps = orjson.dumps sends binary WebSocket frames

orjson.dumps returns bytes; json.dumps returns str. The websockets library passes both to the wire but bytes → binary frame, str → text frame. Kalshi's API almost certainly expects text frames. The ws_json_loads docstring helpfully says "set to e.g. orjson.loads", but the ws_json_dumps docstring is silent on this asymmetry. A user who pairs orjson.dumps for consistency will silently switch to binary frames.

Suggest adding to the ws_json_dumps docstring:

Note: if the callable returns bytes (e.g. orjson.dumps), outbound frames will be sent as binary WebSocket frames. Kalshi's API expects text frames — use only callables that return str for this field.

3. monkeypatch typed as object in one test (tests/ws/test_orderbook.py:752)

def test_apply_delta_inplace_does_not_call_to_orderbook(
    self, monkeypatch: object,   # <-- should be pytest.MonkeyPatch
) -> None:

Every other test in the file uses monkeypatch: pytest.MonkeyPatch. This one uses object, which will fail mypy strict since object has no setattr method, requiring the # type: ignore[attr-defined] suppressions on lines 767/768. Fixing the annotation removes the need for those suppressions.


Positives

  • _open_socket helper is exactly the right refactor for WS: expose ws_ping_interval / ws_close_timeout via KalshiConfig (currently hardcoded) #208 — one place to update connect args, zero drift risk between connect and reconnect.
  • Full Jitter formula is correct and the test precisely pins the upper bounds across all attempts. The jitter window growing proportionally to delay eliminates the thundering-herd cliff.
  • In-place orderbook variants cleanly preserve back-compat for direct callers of the public API while removing the allocation on the hot path. The spy test that asserts to_orderbook is never called is the right way to enforce this invariant.
  • put_sentinel idempotency — the guard at the top of put_sentinel is minimal and correct. Test covers the exact eviction scenario from the bug description.
  • Literal['yes','no'] — tighter than str, the trailing-whitespace rejection test is a nice edge case.
  • Test coverage across all 6 changes is thorough and well-targeted.

Summary

Two actionable items: fix the dead else None branch in apply_delta (correctness) and add a docs note about ws_json_dumps returning bytes (API safety). The monkeypatch type is a minor cleanup. Everything else looks good to merge.

@TexasCoding
TexasCoding merged commit 02bbaef into main May 21, 2026
5 checks passed
@TexasCoding
TexasCoding deleted the audit/w2a-ws-perf-config branch May 21, 2026 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant