Repository navigation
fix(azure_storage): keep the DataLakeServiceClient alive until its TTL elapses - #43082
Conversation
…L elapses Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
…meout Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ata Lake sink Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
|
@greptileai please review the current head e695133 |
…nk back Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
|
bugbot run |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…o the unflushed queue Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
bugbot run |
|
@greptileai review latest head |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0b7c9ee. Configure here.
| try: | ||
| return [ | ||
| path.name | ||
| for path in fs_client.get_paths() |
There was a problem hiding this comment.
Unbounded Azure object listing
Each poll for one response ID lists every path in the filesystem, and the exactly-one check lists them all again. As audit records accumulate, these tests will make increasingly expensive listings and may time out even when the object was delivered. Limit the lookup to the relevant paths or date directories.
…2e-dev dependency Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…_client_ttl Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> # Conflicts: # tests/integration/observability/_azure_storage_support.py # tests/unit/integrations/azure_storage/test_azure_storage.py
…ject_key_prefix * upstream/main: (62 commits) fix(guardrails): scan Responses API input in Azure Prompt Shield (BerriAI#43786) feat(lens): investigate sampled traces and retain batch results (BerriAI#43942) fix(proxy): restore pre-config-wins handling of pass-through endpoints (BerriAI#43962) fix(cost-map): raise baseten DeepSeek-V4.1-Flash max output to 262144 (BerriAI#43916) chore(cost-map): add deprecation date for anthropic claude-sonnet-4-5 (BerriAI#43898) chore(cost-map): add fireworks inkling priority prices from the prices api (BerriAI#43949) feat(guardrails): honor litellm_params.timeout in every HTTP guardrail (BerriAI#43134) test(e2e): typed per-test metadata for the e2e suite (BerriAI#42044) fix(caching): write the response-cache SET to Redis at once instead of on the post-call batch (BerriAI#43973) feat(ui): filter tags by name and description on the Tag Management page (BerriAI#42949) feat(providers): add Cortecs as an OpenAI-compatible provider (BerriAI#43872) feat(e2e): record each e2e test's steps, starting with ProxyClient (BerriAI#42393) test(ci): repair stale tests and move retired OpenAI text-completion fixtures (BerriAI#43958) feat(proxy): record in spend logs whether a request used a client-forwarded Anthropic OAuth token (BerriAI#43063) fix(azure_storage): keep the DataLakeServiceClient alive until its TTL elapses (BerriAI#43082) chore(deps): bump gitpython and tornado, extend diskcache osv ignore to Nov 1 (BerriAI#43961) fix(guardrails): treat an unknown straiker api_version as unset instead of skipping the guardrail (BerriAI#43956) fix(azure_storage): name Data Lake objects without base64 padding or slashes (BerriAI#43914) fix(grayswan): send request conversation and tool calls to post-call monitor (BerriAI#43770) chore(cost-map): sync openrouter prices from the models API (BerriAI#43950) ...
TLDR
Problem this solves:
azure_storageaccount-key uploads close their Data Lake client on almost every callHow it solves it:
tests/integration/observability/cells against a local Data Lake sinkUser Flow
Before: a proxy admin with
success_callback: [azure_storage]andAZURE_STORAGE_ACCOUNT_KEYset finds only part of their traffic in storageazure.core.exceptions.ClientAuthenticationError: (AuthenticationFailed)for many of themAfter: every successful call lands in storage
Linear ticket
Resolves LIT-8601
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/unit/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Two proofs, each base vs head. The reproduction runs against a real Azure Data Lake Gen2 account (isolated resource group, account key in the proxy env only). The deterministic one is the integration audit for LIT-8601 at this PR's tip: real proxy with two workers, Postgres and Redis, scripted upstream, local TLS sink speaking the Data Lake REST surface the SDK emits, no provider call, no credential. Runner
uv run --no-sync python tests/integration/run.pyovertests/integration/observability/test_azure_storage_client_ttl.pyandtest_azure_storage_chaos.py, same--seedand--order-seedon every run, run idsphase12/0b7c9ee496/base,phase12/0b7c9ee496/head1,phase12/0b7c9ee496/head2. After the fresh merge of main at f37a0c4 (which brings the LIT-9079 filename fix and itstest_azure_storage_file_names.pycell), the same selection plus that cell was rerun on the merged tip: 16 passed, 0 skipped, in 540sObservable for the deterministic proof: TCP connections the sink accepts per upload. One live
DataLakeServiceClientpools one blob plus one dfs connection per proxy worker; a client rebuilt per upload opens a fresh pair every timeBefore (merge base 501ef23, unfixed code)
Reproduction against real Azure
AzureBlobStorageLoggerwith the account key, 40 uploads at once (the same shape as the ticket's controlled test): 20/40 objects land, 20AssertionErrors from the aiohttp transport because the next caller closes the shared client mid requestDeterministic audit, 15 azure nodes, 13 passed, 2 failed, 0 skipped
tests/integration/observability/test_azure_storage_client_ttl.py::test_every_surface_lands_once_and_the_client_is_reused_across_uploads: 18 uploads across chat, messages and responses (stream and non stream, openai, anthropic and httpx clients) all land by id, thenAssertionError: 36 sink connections for 18 uploadstests/integration/observability/test_azure_storage_chaos.py::test_slow_sink_lands_every_id_once_without_deadlock: 36 concurrent uploads land once each, thenAssertionError: 72 sink connections for 36 uploads/v1/filessibling, the disabled callback and the restart bound are unchanged from baseAfter (0b7c9ee, test set unchanged at f37a0c4)
Reproduction against real Azure
Deterministic audit, 15 azure nodes, 15 passed, 0 skipped, run twice with identical collected and passed sets; 16 of 16 at the merged tip f37a0c4
Unit regression:
test_service_client_is_reused_until_its_ttl_elapses,test_service_client_is_replaced_once_its_ttl_elapsesandtest_service_client_is_replaced_at_the_exact_ttl_boundaryintests/unit/integrations/azure_storage/test_azure_storage.py. Mutations: flip<=back to>and the first fails, drop the TTL branch and the second fails, change<=to<and the third failsNot run as an integration cell: E1 exact TTL boundary through a running proxy (the clock is a constructor argument the proxy does not expose and the TTL is a module constant, so it stays at the unit level). S5 Entra ID and the real upload path were run live as listed above and are out of the deterministic audit's scope by design; the earlier opt-in
tests/e2e/loggingcells and theire2e-devdependency were dropped from this PR on request, sopyproject.tomlanduv.lockare untouchedReviewer must know before approving
_DEFAULT_TTL_FOR_HTTPX_CLIENTS)AzureBlobStorageLoggergains aclockconstructor argumenttime.time()directlyclock: Callable[[], float] = time.timeis injectable; the proxy never passes it, so runtime behavior is identical and only tests use itType
🐛 Bug Fix
✅ Test
Caveats (if any)
Medium
integration-extensionsis unconfirmed at f37a0c4ci/circleci: integration-*statusesAuthenticationFailedtext was not observed in any run; what reproduces is the shared-client transport failure and the resulting missing objectsLow
{date}/{id}.jsonwhile the Entra ID path writes{id}.jsonat the filesystem root; pre-existing on both legs, unifying the layout is a follow-upextensionsgroup still carries unrelated failures on the audit box (test_redis_outage_keeps_serving_in_memory_hits, the bedrock SigV4 guardrail node,test_passthrough_worker_sigkill_leaves_sibling_serving_and_logging) and one pre-existingBUG:skip; the azure nodes are deterministic and skip freeFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/5c920e07636044cebaef8e7a723300fe
Open in Devin Desktop: https://app.devin.ai/desktop/session/5c920e07636044cebaef8e7a723300fe?variant=devin
Requested by: @yucheng-berri