Repository navigation
Description
Problem
v2.4 #223 added _post_json / _delete_with_body_json helpers for batch endpoints with the rationale: "skips the dict-walk pass httpx's json= does. Use this when a Pydantic model already produced the wire bytes via model_dump_json(...).encode()." V1 batch_create / batch_cancel were rewired through _build_batch_create_body / _build_batch_cancel_body returning bytes and POSTed via _post_json / _delete_with_body_json.
The corresponding V2 methods (batch_create_v2, batch_cancel_v2) still call request.model_dump(mode='json') to produce a dict and ship it through _post(json=...) / _delete_with_body(json=...), so every V2 batch pays the Pydantic-walk-to-dict + httpx-walk-to-bytes overhead twice — exactly the cost #223 measured and removed for V1. With up to 100 orders × ~6-10 Decimal fields per V2 entry, that's hundreds of redundant dict-walks per batch.
The V2 surface is the spec-recommended path for new code (V1 deprecation "no earlier than May 6, 2026" per README); leaving the perf regression on the recommended path is a regression of #223's own contract.
Evidence
kalshi/resources/orders.py:534-539— V1 batch_create already on the fast path:
body = _build_batch_create_body(request, orders)
data = self._post_json(
"/portfolio/orders/batched", content=body, extra_headers=extra_headers
)kalshi/resources/orders.py:866-886— V2 batch_create / batch_cancel still on the slow path:
def batch_create_v2(
self, *, request: BatchCreateOrdersV2Request, extra_headers: dict[str, str] | None = None
) -> BatchCreateOrdersV2Response:
self._require_auth()
body = request.model_dump(exclude_none=True, by_alias=True, mode="json")
data = self._post(
"/portfolio/events/orders/batched", json=body, extra_headers=extra_headers
)
...
def batch_cancel_v2(...):
...
body = request.model_dump(exclude_none=True, by_alias=True, mode="json")
data = self._delete_with_body(
"/portfolio/events/orders/batched", json=body, extra_headers=extra_headers
)CHANGELOG.mdv2.4 Polish bundle: perf + testing (cursor guard O(1), model_dump_json bytes, bench scripts, from_env precedence test, integration env isolation, KalshiAuth.close terminality) #223 — "Batch order bodies serialized once. Resource layer routes batch_create/batch_cancel through new_post_json/_delete_with_body_jsonbytes helpers that usemodel_dump_json+httpx content=, skipping one full dict-walk per call."
Suggested fix
Add _build_batch_create_v2_body / _build_batch_cancel_v2_body helpers next to the existing V1 builders that call request.model_dump_json(exclude_none=True, by_alias=True).encode(). Route batch_create_v2 through _post_json(content=body, ...) and batch_cancel_v2 through _delete_with_body_json(content=body, ...). Mirror the changes on AsyncOrdersResource. Extend scripts/bench_request_hot_path.py (or add a new V2-specific bench) to lock in parity with V1.
Source
Round-3 independent audit (reviewer: resources_api).
Activity
polish(resources): communications status Literal + V2 batch bytes-fas…