litellm/tests/unit/caching/_event_loop_reuse.py
paveln83 4ce724e3df
fix(caching): key cached async clients by a per-loop token instead of id(loop) (#48877)
* fix(caching): key cached async clients by a per-loop token instead of id(loop)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(caching): drop deferred closes queued on a collected event loop

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(caching): pin that a close queued on a live loop waits for that loop

* test(caching): run loop-reuse tests until a loop address repeats

The collected-loop tests ran a fixed 50 loops and passed with the fix reverted whenever no loop reused an earlier address. They now stop at the first reuse and skip if none happens, through a shared helper.

* test(caching): cover the cache key fallback for loops without weak references

Also corrects the evicted client closer docstring: a dropped bucket's clients are left to the garbage collector.

* fix(http): free short-lived event loops whose handler finalizer close finished as the loop stopped

* fix(caching): share sync clients across event loops and catch a failed finalizer close

* fix(agentops): stop closing the shared sync http client after the auth call

---------

Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-29 13:14:48 -07:00

20 lines
690 B
Python

from collections.abc import Callable
from typing import Final, TypeVar
import pytest
LoopResult = TypeVar("LoopResult")
def runs_until_a_loop_address_repeats(
run_on_new_loop: Callable[[], tuple[int, LoopResult]],
earlier: tuple[tuple[int, LoopResult], ...] = (),
limit: int = 50,
) -> tuple[tuple[int, LoopResult], ...]:
if len(earlier) == limit:
pytest.skip(f"none of {limit} collected loops had its address handed to a later loop")
latest: Final = run_on_new_loop()
runs: Final = (*earlier, latest)
if latest[0] in {loop_id for loop_id, _ in earlier}:
return runs
return runs_until_a_loop_address_repeats(run_on_new_loop, runs, limit)