litellm/tests/test_litellm/llms/test_lifecycle_fix.py
2026-04-17 13:02:59 -07:00

48 lines
1.5 KiB
Python

"""
Verifies that the httpx client used by AsyncOpenAI is NOT closed
when AsyncHTTPHandler instances are garbage collected.
"""
import asyncio
import gc
import httpx
from litellm.llms.openai.common_utils import BaseOpenAILLM
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler
async def test_httpx_client_not_closed_by_handler_gc():
"""
Before the fix: _get_async_http_client() returned handler.client,
so when handler was GC'd its __del__ closed the client.
After the fix: returns a standalone httpx.AsyncClient, no handler involved.
"""
# Get the client the same way AsyncOpenAI would
client = BaseOpenAILLM._get_async_http_client()
assert isinstance(client, httpx.AsyncClient)
# Simulate what the old code did: create an AsyncHTTPHandler and GC it
handler = AsyncHTTPHandler()
handler_client = handler.client
del handler
gc.collect()
# The client from _get_async_http_client should still be open
# because it's NOT tied to any AsyncHTTPHandler
assert not client.is_closed, "Client was closed prematurely!"
# Verify it can actually send (build a request without sending)
try:
req = client.build_request("GET", "https://example.com")
print("PASS: Client is still usable after handler GC")
except RuntimeError as e:
if "closed" in str(e):
print(f"FAIL: {e}")
raise
raise
await client.aclose()
print("All checks passed!")
asyncio.run(test_httpx_client_not_closed_by_handler_gc())