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
{{ message }}
Repository navigation
Polish bundle: auth + transport small items (sign-executor race, Retry-After negative) #267
Small transport / auth quality improvements bundled for a single PR.
Item 1 — _get_sign_executor checks _closed outside the lock
If sign_request_async and close() race, thread A can read _closed=False, then close() runs end-to-end (sets _closed=True, shuts down + nulls the executor), then thread A enters the double-checked init under the lock and constructs a brand-new ThreadPoolExecutor on a closed auth. That executor never gets shut down (close() already returned and won't be called again), defeating the documented terminality and leaving a 2-thread pool dangling until interpreter shutdown.
Fix: Move the self._closed check inside the lock (or recheck after acquiring it), and raise without instantiating a new executor when _closed is True.
Item 2 — Retry-After delta-seconds vs HTTP-date treatment of "past/negative" is inconsistent
# delta-seconds form: negative or NaN -> None -> falls back to computed backoffretry_after_val=float(retry_after)
ifretry_after_val<0ornotmath.isfinite(retry_after_val):
retry_after_val=None# HTTP-date form: past date -> 0.0 -> retry immediatelydelta= (dt-datetime.now(tz=UTC)).total_seconds()
retry_after_val=max(0.0, delta)
A server (or proxy with clock skew) that emits Retry-After: -5 waits the computed exponential backoff, while the semantically equivalent Retry-After: <past HTTP-date> retries immediately. Tests that pin one shape will silently disagree with the other.
Location: kalshi/_base_client.py:84-120.
Fix: Pick one policy and apply to both — clamping to 0.0 in both branches is the more permissive choice and matches the existing date-form behavior; alternatively treat negative/past as None in both.
Activity
polish(auth+transport): sign-executor race, Retry-After parity, Messa…
fix-up(transport): note thread-safety scope on close() idempotence
polish(transport): make Sync/AsyncTransport.close() explicitly idempo…
fix(transport): Retry-After on 5xx/408 + jittered + success body cap (#…