Skip to content

Commit 5f58c82

Browse files
committed
fix(harness): configure HTTP write timeout
1 parent dacd638 commit 5f58c82

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

harness/src/harness/http_pool.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def get_client(self) -> httpx.Client:
7777
timeout=httpx.Timeout(
7878
connect=self._config.connect_timeout,
7979
read=self._config.read_timeout,
80+
write=self._config.timeout,
8081
pool=self._config.pool_timeout,
8182
),
8283
http2=True, # Enable HTTP/2 for better multiplexing
@@ -98,6 +99,7 @@ def get_async_client(self) -> httpx.AsyncClient:
9899
timeout=httpx.Timeout(
99100
connect=self._config.connect_timeout,
100101
read=self._config.read_timeout,
102+
write=self._config.timeout,
101103
pool=self._config.pool_timeout,
102104
),
103105
http2=True,

harness/tests/test_http_pool.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""Timeout construction coverage for :mod:`harness.http_pool`."""
2+
3+
import asyncio
4+
5+
import pytest
6+
7+
from harness.http_pool import (
8+
HTTPConnectionPool,
9+
PoolConfig,
10+
get_async_http_client,
11+
get_http_client,
12+
)
13+
14+
15+
def _reset_pool_safely() -> None:
16+
"""Close factory clients without exercising ``HTTPConnectionPool.close``.
17+
18+
The production async-close path has separate event-loop behavior. These
19+
synchronous factory tests own the clients they create and close them using
20+
a fresh loop, so singleton cleanup cannot leak clients between tests.
21+
"""
22+
with HTTPConnectionPool._lock:
23+
pool = HTTPConnectionPool._instance
24+
HTTPConnectionPool._instance = None
25+
26+
if pool is None:
27+
return
28+
29+
if pool._client is not None:
30+
pool._client.close()
31+
pool._client = None
32+
if pool._async_client is not None:
33+
asyncio.run(pool._async_client.aclose())
34+
pool._async_client = None
35+
36+
37+
@pytest.fixture(autouse=True)
38+
def reset_http_connection_pool() -> None:
39+
_reset_pool_safely()
40+
try:
41+
yield
42+
finally:
43+
_reset_pool_safely()
44+
45+
46+
def _configured_timeout() -> PoolConfig:
47+
return PoolConfig(
48+
timeout=47.0,
49+
connect_timeout=11.0,
50+
read_timeout=23.0,
51+
pool_timeout=5.0,
52+
)
53+
54+
55+
def _assert_configured_timeout(timeout: object) -> None:
56+
assert getattr(timeout, "connect") == 11.0
57+
assert getattr(timeout, "read") == 23.0
58+
assert getattr(timeout, "write") == 47.0
59+
assert getattr(timeout, "pool") == 5.0
60+
61+
62+
def test_get_http_client_configures_all_timeout_phases() -> None:
63+
client = get_http_client(_configured_timeout())
64+
65+
_assert_configured_timeout(client.timeout)
66+
67+
68+
def test_get_async_http_client_configures_all_timeout_phases() -> None:
69+
client = get_async_http_client(_configured_timeout())
70+
71+
_assert_configured_timeout(client.timeout)

0 commit comments

Comments
 (0)