SPB Git forge
28commits 1branches 0releases
7.7 MBsize
maindefault branch
10 days agolast push
Python 66.3% TypeScript 22.7% JavaScript 8.6% HTML 1.4% CSS 0.7%

fetch: HTTP/1.1 by default (h2 SEND_SETTINGS protocol errors), protocol errors classified transient; scheduler capacity 48/400

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 11 days ago (Sep 13, 2026) parent 01ee6ea

2 changed files +8 −3

modified deploy/company-atlas.mld.json +2 −1
@@ -114,7 +114,8 @@
114 114 "CA_ADMIN_TOKEN": "{{ADMIN_TOKEN}}",
115 115 "CA_LLM_BASE_URL": "https://www.llm-api.io/v1",
116 116 "CA_LLM_API_KEY": "{{LLM_KEY}}",
117 − "CA_FETCH_CONCURRENCY": "32",
117 + "CA_FETCH_CONCURRENCY": "48",
118 + "CA_SCHEDULER_CLAIM_BATCH": "400",
118 119 "CA_ONBOARDING_CONCURRENCY": "12",
119 120 "CA_DB_POOL_SIZE": "12",
120 121 "CA_DB_MAX_OVERFLOW": "12",
modified src/companyatlas/fetch.py +6 −2
@@ -256,6 +256,8 @@ def classify_exception(exc: BaseException) -> FailureClass:
256 256 return exc.failure
257 257 if isinstance(exc, httpx.ConnectTimeout | httpx.ReadTimeout | httpx.WriteTimeout | httpx.PoolTimeout | asyncio.TimeoutError | TimeoutError):
258 258 return FailureClass.TIMEOUT
259 + if isinstance(exc, httpx.RemoteProtocolError | httpx.ProtocolError) or exc.__class__.__name__ in ("ProtocolError", "StreamReset", "ConnectionTerminated"):
260 + return FailureClass.TIMEOUT # transient transport-level protocol errors (h2 connection reuse, resets): retry policy, not a mystery
259 261 if isinstance(exc, httpx.ConnectError):
260 262 msg = str(exc).lower()
261 263 if "nodename" in msg or "name or service" in msg or "getaddrinfo" in msg or "temporary failure in name" in msg or "no address" in msg:
@@ -355,9 +357,11 @@ robots = RobotsCache()
355 357
356 358
357 359 class Fetcher:
358 − """Shared httpx client (one per worker process). `get()` raises NotModified / FetchError / BlockedError."""
360 + """Shared httpx client (one per worker process). `get()` raises NotModified / FetchError / BlockedError.
361 + HTTP/1.1 by default: h2 connection reuse against thousands of heterogeneous origins produced `ConnectionInputs.SEND_SETTINGS in state CLOSED`
362 + protocol errors (2026-09-13); HTTP/2 stays available per Fetcher (`http2=True`)."""
359 363
360 − def __init__(self, *, timeout_s: float | None = None, headers: dict[str, str] | None = None, http2: bool = True,
364 + def __init__(self, *, timeout_s: float | None = None, headers: dict[str, str] | None = None, http2: bool = False,
361 365 max_connections: int | None = None):
362 366 self.timeout_s = timeout_s or settings.http_timeout_s
363 367 self.headers = {"User-Agent": settings.user_agent,
364 368