11import asyncio
2- from contextlib import asynccontextmanager
32from typing import Any
43
54import httpx
@@ -40,23 +39,20 @@ class HTTPXClient:
4039 }
4140
4241 @classmethod
43- @asynccontextmanager
44- async def get_client (cls ):
42+ async def _ensure_client (cls ) -> httpx .AsyncClient :
4543 async with cls ._lock :
4644 if cls ._client is None or cls ._client .is_closed :
4745 cls ._client = httpx .AsyncClient (
4846 timeout = cls .DEFAULT_TIMEOUT ,
4947 )
50- try :
51- yield cls ._client
52- except httpx .TransportError as e :
53- logger .error (f"httpx client transport error: { e } " )
54- await cls .close ()
55- cls ._client = None
56- raise
57- except httpx .HTTPError as e :
58- logger .warning (f"httpx client HTTP error: { e } " )
59- raise
48+ return cls ._client
49+
50+ @classmethod
51+ async def _reset_client (cls ) -> None :
52+ async with cls ._lock :
53+ if cls ._client and not cls ._client .is_closed :
54+ await cls ._client .aclose ()
55+ cls ._client = None
6056
6157 @classmethod
6258 async def close (cls ):
@@ -76,10 +72,15 @@ def configure_defaults(cls, timeout: float = DEFAULT_TIMEOUT, retry_config: dict
7672 async def get (cls , url : str , ** kwargs ) -> httpx .Response | None :
7773 @retry (** cls .DEFAULT_RETRY )
7874 async def _get ():
79- async with cls .get_client () as client :
75+ client = await cls ._ensure_client ()
76+ try :
8077 response = await client .get (url , ** kwargs )
8178 response .raise_for_status ()
8279 return response
80+ except httpx .TransportError as e :
81+ logger .error (f"httpx client transport error: { e } " )
82+ await cls ._reset_client ()
83+ raise
8384
8485 try :
8586 return await _get ()
@@ -91,10 +92,15 @@ async def _get():
9192 async def post (cls , url : str , json : dict [str , Any ] | None = None , ** kwargs ) -> httpx .Response | None :
9293 @retry (** cls .DEFAULT_RETRY )
9394 async def _post ():
94- async with cls .get_client () as client :
95+ client = await cls ._ensure_client ()
96+ try :
9597 response = await client .post (url , json = json , ** kwargs )
9698 response .raise_for_status ()
9799 return response
100+ except httpx .TransportError as e :
101+ logger .error (f"httpx client transport error: { e } " )
102+ await cls ._reset_client ()
103+ raise
98104
99105 try :
100106 return await _post ()
@@ -106,10 +112,15 @@ async def _post():
106112 async def delete (cls , url : str , ** kwargs ) -> httpx .Response | None :
107113 @retry (** cls .DEFAULT_RETRY )
108114 async def _delete ():
109- async with cls .get_client () as client :
115+ client = await cls ._ensure_client ()
116+ try :
110117 response = await client .delete (url , ** kwargs )
111118 response .raise_for_status ()
112119 return response
120+ except httpx .TransportError as e :
121+ logger .error (f"httpx client transport error: { e } " )
122+ await cls ._reset_client ()
123+ raise
113124
114125 try :
115126 return await _delete ()
0 commit comments