Skip to content

Commit f4ecc31

Browse files
thodson-usgsclaude
andcommitted
test(waterdata): close server-leak window in pool-timeout regression test
The ThreadingHTTPServer thread was started before the try block, so a setup failure between thread.start() and the try (monkeypatch, decorator construction) would leak the serve_forever thread and its bound socket — the finally never ran. Move the try up to immediately after the thread starts so teardown always fires. (server.shutdown() stays safe: it's only reachable once serve_forever is running.) Surfaced by the code-review sweep. No production change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 07b3381 commit f4ecc31

1 file changed

Lines changed: 16 additions & 14 deletions

File tree

tests/waterdata_chunking_test.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,23 +1583,25 @@ def log_message(self, *args): # keep pytest output clean
15831583
server = http.server.ThreadingHTTPServer(("127.0.0.1", 0), _SlowHandler)
15841584
thread = threading.Thread(target=server.serve_forever, daemon=True)
15851585
thread.start()
1586-
url = f"http://127.0.0.1:{server.server_address[1]}/"
1586+
# Everything past the thread start is in the try, so any setup failure
1587+
# (monkeypatch, decorator construction) still tears the server down.
1588+
try:
1589+
url = f"http://127.0.0.1:{server.server_address[1]}/"
15871590

1588-
# Scale the production pool timeout (see ``HTTPX_DEFAULTS``) down to
1589-
# 0.2 s so the pre-semaphore failure mode reproduces in test time.
1590-
monkeypatch.setitem(
1591-
HTTPX_DEFAULTS, "timeout", httpx.Timeout(5.0, connect=1.0, pool=0.2)
1592-
)
1591+
# Scale the production pool timeout (see ``HTTPX_DEFAULTS``) down to
1592+
# 0.2 s so the pre-semaphore failure mode reproduces in test time.
1593+
monkeypatch.setitem(
1594+
HTTPX_DEFAULTS, "timeout", httpx.Timeout(5.0, connect=1.0, pool=0.2)
1595+
)
15931596

1594-
async def fetch_async(args):
1595-
client = get_active_client()
1596-
assert client is not None, "sub-request must use the shared client"
1597-
resp = await client.get(url)
1598-
assert resp.status_code == 200
1599-
return pd.DataFrame({"id": [_atom_id(args)]}), resp
1597+
async def fetch_async(args):
1598+
client = get_active_client()
1599+
assert client is not None, "sub-request must use the shared client"
1600+
resp = await client.get(url)
1601+
assert resp.status_code == 200
1602+
return pd.DataFrame({"id": [_atom_id(args)]}), resp
16001603

1601-
sites = _EIGHT_SINGLETON_SITES[:4] # 2 in flight + 2 queued, 2 waves
1602-
try:
1604+
sites = _EIGHT_SINGLETON_SITES[:4] # 2 in flight + 2 queued, 2 waves
16031605
fetch = _async_chunked_fetch(monkeypatch, fetch_async, max_concurrent=2)
16041606
df, _ = fetch({"sites": sites})
16051607
assert len(df) == len(sites)

0 commit comments

Comments
 (0)