Spawn a daemon thread that fires HEAD ``url``; return immediately. The thread completes (or times out) on its own. ``daemon=True`` so a slow handshake never blocks process exit.
(url: str = _DEFAULT_PRECONNECT_URL)
| 71 | |
| 72 | |
| 73 | def start_api_preconnect(url: str = _DEFAULT_PRECONNECT_URL) -> PreconnectHandle: |
| 74 | """Spawn a daemon thread that fires HEAD ``url``; return immediately. |
| 75 | |
| 76 | The thread completes (or times out) on its own. ``daemon=True`` so a |
| 77 | slow handshake never blocks process exit. |
| 78 | """ |
| 79 | if should_skip_preconnect(): |
| 80 | return PreconnectHandle(thread=None, skipped=True) |
| 81 | |
| 82 | def _do_preconnect() -> None: |
| 83 | # Lazy import inside the thread so importing this module doesn't |
| 84 | # pull in httpx on the cold-start path. |
| 85 | try: |
| 86 | import httpx |
| 87 | except ImportError: # pragma: no cover |
| 88 | return |
| 89 | try: |
| 90 | with httpx.Client(timeout=_PRECONNECT_TIMEOUT_S) as client: |
| 91 | # HEAD warms the handshake without transferring a body. |
| 92 | # 4xx/5xx are fine — we just want the TCP+TLS session. |
| 93 | client.head(url) |
| 94 | except Exception: |
| 95 | # Best-effort: never let preconnect failures bubble up. |
| 96 | pass |
| 97 | |
| 98 | thread = threading.Thread( |
| 99 | target=_do_preconnect, |
| 100 | name="api-preconnect", |
| 101 | daemon=True, |
| 102 | ) |
| 103 | thread.start() |
| 104 | return PreconnectHandle(thread=thread, skipped=False) |