Skip to content

Commit 40c126c

Browse files
committed
Add graceful clean up for responses
1 parent 444e042 commit 40c126c

File tree

4 files changed

+35
-2
lines changed

4 files changed

+35
-2
lines changed

httpcore/_async/connection_pool.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,12 @@ def __init__(
342342
self._pool = pool
343343
self._status = status
344344

345+
@AutoBackend.graceful_call
346+
async def _force_clean_up(self) -> None:
347+
if hasattr(self._stream, "aclose"):
348+
await self._stream.aclose()
349+
await self._pool.response_closed(self._status)
350+
345351
async def __aiter__(self) -> AsyncIterator[bytes]:
346352
async for part in self._stream:
347353
yield part
@@ -351,4 +357,4 @@ async def aclose(self) -> None:
351357
if hasattr(self._stream, "aclose"):
352358
await self._stream.aclose()
353359
finally:
354-
await self._pool.response_closed(self._status)
360+
await self._force_clean_up()

httpcore/_sync/connection_pool.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,12 @@ def __init__(
342342
self._pool = pool
343343
self._status = status
344344

345+
@SyncBackend.graceful_call
346+
def _force_clean_up(self) -> None:
347+
if hasattr(self._stream, "close"):
348+
self._stream.close()
349+
self._pool.response_closed(self._status)
350+
345351
def __iter__(self) -> Iterator[bytes]:
346352
for part in self._stream:
347353
yield part
@@ -351,4 +357,4 @@ def close(self) -> None:
351357
if hasattr(self._stream, "close"):
352358
self._stream.close()
353359
finally:
354-
self._pool.response_closed(self._status)
360+
self._force_clean_up()

httpcore/backends/auto.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import typing
22
from typing import Optional
33

4+
import anyio
45
import sniffio
56

67
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
78

9+
_TP = typing.ParamSpec("_TP")
10+
_R = typing.TypeVar("_R")
11+
812

913
class AutoBackend(AsyncNetworkBackend):
1014
async def _init_backend(self) -> None:
@@ -50,3 +54,13 @@ async def connect_unix_socket(
5054
async def sleep(self, seconds: float) -> None: # pragma: nocover
5155
await self._init_backend()
5256
return await self._backend.sleep(seconds)
57+
58+
@staticmethod
59+
def graceful_call(
60+
fnc: typing.Callable[_TP, typing.Awaitable[_R]]
61+
) -> typing.Callable[_TP, typing.Awaitable[_R]]:
62+
async def inner(*args: _TP.args, **kwargs: _TP.kwargs) -> _R:
63+
with anyio.CancelScope(shield=True):
64+
return await fnc(*args, **kwargs)
65+
66+
return inner

httpcore/backends/sync.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
from .._utils import is_socket_readable
1717
from .base import SOCKET_OPTION, NetworkBackend, NetworkStream
1818

19+
_TP = typing.ParamSpec("_TP")
20+
_R = typing.TypeVar("_R")
21+
1922

2023
class SyncStream(NetworkStream):
2124
def __init__(self, sock: socket.socket) -> None:
@@ -131,3 +134,7 @@ def connect_unix_socket(
131134
sock.settimeout(timeout)
132135
sock.connect(path)
133136
return SyncStream(sock)
137+
138+
@staticmethod
139+
def graceful_call(fnc: typing.Callable[_TP, _R]) -> typing.Callable[_TP, _R]:
140+
return fnc

0 commit comments

Comments
 (0)