Skip to content

refactor(python): move run-compression init into Client.__init__#2798

Draft
Angus Jelinek (angus-langchain) wants to merge 1 commit into
mainfrom
refactor/compression-init-at-startup
Draft

refactor(python): move run-compression init into Client.__init__#2798
Angus Jelinek (angus-langchain) wants to merge 1 commit into
mainfrom
refactor/compression-init-at-startup

Conversation

@angus-langchain
Copy link
Copy Markdown
Contributor

Summary

Compression setup previously ran inside tracing_control_thread_func after the first client.info fetch. This asynchronous gate meant runs created before the server-flag handshake completed lived in tracing_queue, while later runs went to compressed_traces — a race that required a defensive fix in #2796.

The server-side zstd_compression_enabled flag is now assumed to be set on every supported deployment (cloud and all self-hosted versions), so the asynchronous gate is no longer needed.

Changes

  • Compression state (compressed_traces, _data_available_event, _futures) is initialized in Client.__init__ using only local signals: ZSTD_AVAILABLE, DISABLE_RUN_COMPRESSION, tracing mode, auto_batch_tracing, and user-provided batch_ingest_config.use_multipart_endpoint.
  • Both the tracing and compression background threads spawn from __init__, so compressed_traces is either set or None for the lifetime of the client — no mid-flight transition.
  • The server-flag check and the "Please update to the latest version of LangSmith" warning are removed from _background_thread.py. num_known_refs in the tracing thread is now computed from client.compressed_traces is not None.
  • tracing_queue still exists and handles per-request auth/URL overrides, OTel mode, and the ZSTD-not-installed fallback. The race fix from fix(python): flush both tracing_queue and compressed_traces in flush() #2796 stands as defense in depth.

Test changes

  • parse_request_data (tests/unit_tests/conftest.py) now detects zstd frames and streams-decompresses them, so existing payload assertions keep working without per-test changes.
  • A few tests that assert the non-compressed multipart payload structure (attachments, raw bytes data) now opt out via LANGSMITH_DISABLE_RUN_COMPRESSION=true rather than relying on the (now-gone) server-flag behaviour.
  • test_create_run_without_compression_support is deleted — the server-doesn't-support-compression scenario no longer exists.
  • test_client_gc uses client.flush() instead of client.tracing_queue.join() so it drains both queues.

Compression setup previously ran inside tracing_control_thread_func after
the first client.info fetch, which meant runs created before that moment
lived in tracing_queue while later runs went to compressed_traces. The
server-side zstd_compression_enabled flag is now assumed to be set on every
supported deployment (cloud and self-hosted), so the asynchronous gate is
no longer needed.

Now the compression decision is made synchronously in __init__ using only
local signals (ZSTD_AVAILABLE, DISABLE_RUN_COMPRESSION, tracing mode,
auto_batch_tracing, and user-provided batch_ingest_config.use_multipart_endpoint).
The compression thread starts alongside the main tracing thread, so
compressed_traces is either set or None for the lifetime of the client.

Tests that asserted raw-bytes multipart payloads either opt out with
LANGSMITH_DISABLE_RUN_COMPRESSION or decompress via parse_request_data,
which now detects zstd frames and decompresses before parsing. The
test_create_run_without_compression_support case is removed — the scenario
it covered no longer exists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@angus-langchain Angus Jelinek (angus-langchain) marked this pull request as draft April 24, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant