Skip to content

Polish bundle: WS small items (cancelled mid-subscribe leak, snapshot empty-array default) #268

Closed

Description

@TexasCoding

Summary

Small WS quality improvements bundled for a single PR.

Item 1 — Cancelled mid-subscribe leaks a server-side subscription

channels.py:subscribe sends a subscribe cmd and awaits _wait_for_response. If the awaiting task is cancelled between send and ack, the lock is released but the server still completes the subscribe and emits a subscribed ack. That ack hits the dispatcher, where subscribed is silently dropped (no client_id mapping is installed). The server holds an active sid that the client doesn't know about; subsequent frames for that sid log "Message for unknown sid" and are dropped. The leaked sub counts against any server-side sub quota and persists until the WS closes.

Location: kalshi/ws/channels.py:248-310, kalshi/ws/dispatch.py:195-201.

Fix: On CancelledError inside subscribe(), send a best-effort unsubscribe for the in-flight msg_id once an ack arrives, OR have the dispatcher detect orphan subscribed envelopes (sid present, no client_id mapping) and immediately send an unsubscribe.

Item 2 — OrderbookSnapshotPayload yes/no default=[] silently materializes half-empty books

class OrderbookSnapshotPayload(BaseModel):
    market_ticker: str
    market_id: str
    yes: list[tuple[DollarDecimal, FixedPointCount]] = Field(
        default=[],
        validation_alias=AliasChoices("yes_dollars_fp", "yes"),
    )
    no: list[tuple[DollarDecimal, FixedPointCount]] = Field(
        default=[],
        validation_alias=AliasChoices("no_dollars_fp", "no"),
    )

A wire frame missing both yes_dollars_fp and no_dollars_fp (schema drift, partial server response) parses as a completely empty snapshot rather than a ValidationError. The book is reset to empty without any indication. Mutable list as default is also a pydantic anti-pattern.

Location: kalshi/ws/models/orderbook_delta.py:21-30.

Fix: Drop the default=[] — make both sides required so a malformed snapshot is rejected at validation time, where the recv loop already logs it. Pairs naturally with the "validation failure advances seq watermark" fix.

Severity & category

low / polish, ws

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    polishCode-quality and DX improvements; non-functionalwsWebSocket-related

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions