Commit c713659
fix(waterdata): gate the chunked fan-out with a semaphore, not the pool
ChunkedCall._run dispatched every pending sub-request into one
asyncio.gather and relied on the shared httpx.AsyncClient connection
pool as the only concurrency throttle (max_connections sized from
API_USGS_CONCURRENT). That collides with the client's pool-acquire
timeout (60 s, from HTTPX_DEFAULTS):
- Time a sub-request spends queued waiting for a pooled connection
counts against that timeout, and a queued waiter's clock only resets
when some response completes and httpcore reassigns the freed
connection. So whenever every pooled connection stays busy past the
timeout with no completion in between (a batch of large,
slowly-streaming pages), the queued tail of the fan-out fails with
httpx.PoolTimeout. Being a TransportError it burns the per-sub-request
retry budget and ultimately surfaces as a bogus *resumable*
ServiceInterrupted telling the user to wait for the upstream to
recover — for a failure the server never saw.
- Pool queueing also thunders: httpcore assigns a freed connection to
every queued waiter, which all wake and race for it, the losers
re-queuing — O(pending) wakeups per page completion under a large
fan-out.
Gate each fetch attempt with an asyncio.Semaphore sized from
API_USGS_CONCURRENT instead; the connection pool is now merely sized to
match so in-flight sub-requests reuse keepalive connections. Parked
sub-requests wait on the semaphore before they touch the pool, so no
transport clock runs while they wait and the pool timeout reverts to
its protective role (a genuinely wedged checkout). The slot is acquired
per attempt, so a sub-request sleeping off a retry backoff doesn't hold
one. "unbounded" degenerates to a semaphore sized at the plan total, so
there is a single gated code path. Observable behavior is otherwise
unchanged: same plan, same sub-request order, same resume semantics.
Tests:
- in-flight high-water-mark probe (parametrized capped/unbounded) — the
fetch-level concurrency equals the cap, not the plan total; the capped
case fails on the pre-fix code.
- real-localhost-server end-to-end test — mock transports bypass the
pool, so this drives the chunker's shared client against a slow server
past a scaled-down pool timeout; reproduces the spurious resumable
ServiceInterrupted on the pre-fix code and completes on this branch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>1 parent ff8f535 commit c713659
3 files changed
Lines changed: 199 additions & 42 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
130 | 131 | | |
131 | 132 | | |
132 | 133 | | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
137 | 138 | | |
138 | 139 | | |
139 | 140 | | |
| |||
1307 | 1308 | | |
1308 | 1309 | | |
1309 | 1310 | | |
1310 | | - | |
1311 | | - | |
1312 | | - | |
| 1311 | + | |
| 1312 | + | |
| 1313 | + | |
1313 | 1314 | | |
1314 | 1315 | | |
1315 | 1316 | | |
| |||
1551 | 1552 | | |
1552 | 1553 | | |
1553 | 1554 | | |
1554 | | - | |
1555 | | - | |
1556 | | - | |
1557 | | - | |
1558 | | - | |
1559 | | - | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
1560 | 1575 | | |
1561 | 1576 | | |
1562 | 1577 | | |
1563 | 1578 | | |
1564 | 1579 | | |
1565 | 1580 | | |
1566 | | - | |
1567 | | - | |
| 1581 | + | |
| 1582 | + | |
1568 | 1583 | | |
1569 | 1584 | | |
1570 | 1585 | | |
| |||
1583 | 1598 | | |
1584 | 1599 | | |
1585 | 1600 | | |
1586 | | - | |
1587 | | - | |
1588 | | - | |
1589 | | - | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
1590 | 1608 | | |
1591 | 1609 | | |
1592 | 1610 | | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
1593 | 1614 | | |
1594 | 1615 | | |
1595 | 1616 | | |
1596 | 1617 | | |
1597 | 1618 | | |
1598 | 1619 | | |
1599 | 1620 | | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
1600 | 1635 | | |
1601 | 1636 | | |
1602 | 1637 | | |
1603 | 1638 | | |
1604 | | - | |
| 1639 | + | |
1605 | 1640 | | |
1606 | 1641 | | |
1607 | 1642 | | |
| |||
1610 | 1645 | | |
1611 | 1646 | | |
1612 | 1647 | | |
1613 | | - | |
| 1648 | + | |
1614 | 1649 | | |
1615 | 1650 | | |
1616 | 1651 | | |
| |||
1706 | 1741 | | |
1707 | 1742 | | |
1708 | 1743 | | |
1709 | | - | |
1710 | | - | |
| 1744 | + | |
| 1745 | + | |
1711 | 1746 | | |
1712 | 1747 | | |
1713 | 1748 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1551 | 1551 | | |
1552 | 1552 | | |
1553 | 1553 | | |
1554 | | - | |
| 1554 | + | |
1555 | 1555 | | |
1556 | 1556 | | |
1557 | 1557 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
21 | 22 | | |
| 23 | + | |
| 24 | + | |
22 | 25 | | |
23 | 26 | | |
24 | 27 | | |
| |||
32 | 35 | | |
33 | 36 | | |
34 | 37 | | |
| 38 | + | |
35 | 39 | | |
36 | 40 | | |
37 | 41 | | |
| |||
56 | 60 | | |
57 | 61 | | |
58 | 62 | | |
| 63 | + | |
59 | 64 | | |
60 | 65 | | |
61 | 66 | | |
| |||
1314 | 1319 | | |
1315 | 1320 | | |
1316 | 1321 | | |
1317 | | - | |
1318 | | - | |
1319 | | - | |
1320 | | - | |
1321 | | - | |
1322 | | - | |
1323 | | - | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
1324 | 1331 | | |
1325 | 1332 | | |
1326 | 1333 | | |
| |||
1489 | 1496 | | |
1490 | 1497 | | |
1491 | 1498 | | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
1492 | 1614 | | |
1493 | 1615 | | |
1494 | 1616 | | |
| |||
0 commit comments