fix(network): default to IPv4-first DNS ordering to avoid dead-IPv6-route timeouts - #71373
fix(network): default to IPv4-first DNS ordering to avoid dead-IPv6-route timeouts#71373toprakeker wants to merge 1 commit into
Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused transport-level fix. Current main still has only the opt-in force_ipv4 path: apply_ipv4_preference() is a no-op unless forced (hermes_constants.py:1205-1206), and gateway bootstrap calls it only for network.force_ipv4 (gateway/run.py:2122-2127).
Problems
- The CLI default is skipped when
config.yamldoes not exist. The proposed flag assignment remains under_cfg_path.exists()(hermes_cli/main.py:711), so a configless profile never reaches the new IPv4-first call. - Current main moved
DEFAULT_CONFIGintohermes_cli/config_defaults.py(hermes_cli/config.py:935; network defaults atconfig_defaults.py:2298-2304), so the config-default hunk needs relocation. - The config reference currently documents only
force_ipv4(website/docs/user-guide/configuration.md:2265-2274).
Suggested changes
- Apply the default outside the config-exists guard while preserving explicit
ipv4_first: false, with a configless-profile regression test. - Move the default to
config_defaults.pyand document the new option and its interaction withforce_ipv4.
This is an automated hermes-sweeper review.
| _FORCE_IPV4_EARLY = True | ||
| # ipv4_first defaults to True — apply the lighter-weight IPv4-first | ||
| # DNS ordering unless explicitly disabled. | ||
| if _early_net_cfg.get("ipv4_first", True): |
There was a problem hiding this comment.
This assignment is still inside the surrounding _cfg_path.exists() guard. A new/configless profile therefore leaves _IPV4_FIRST_EARLY false and never applies the claimed default; initialize the default outside that guard and override it only when raw config explicitly disables it.
|
Thanks — I addressed the review points in the PR branch.\n\nChanges:\n- CLI now applies the default |
e96abdf to
8dd3bee
Compare
|
Closing this older pre-contributor branch. Network/bootstrap architecture has changed since this was opened, and the fork CI still requires manual approval. I will re-check the underlying IPv6 timeout issue against current main before proposing any fresh fix. |
Fixes #71215.
Problem
Dual-stack hosts whose providers publish AAAA records that route nowhere pay a 10–30 s IPv6 connect timeout on every API call before falling back to IPv4. Python's
socket.getaddrinfo()tries IPv6 first per the default address ordering. The existing workaround (network.force_ipv4: true) fully disables IPv6, which is too aggressive for hosts that genuinely need it for some destinations.Approach
Add a lighter-weight
network.ipv4_firstoption (on by default) that monkey-patchessocket.getaddrinfoto sort results IPv4-first instead of filtering IPv6 out entirely. Both A and AAAA records remain available — IPv4 is just tried first. If no A record exists (pure-IPv6 host), the original ordering is preserved, so IPv6 connectivity is retained.This is applied alongside (and before) the existing
apply_ipv4_preferenceat all three entrypoints:gateway/run.py(gateway bootstrap)cron/scheduler.py(cron scheduler init)hermes_cli/main.py(early CLI bootstrap)Changes
hermes_constants.py: newapply_ipv6_fallback_ordering(enabled: bool = True)matching the style ofapply_ipv4_preference(same guard-against-double-patch pattern, same_hermes_*_patchedattribute convention).hermes_cli/config.py: add"ipv4_first": TruetoDEFAULT_CONFIG["network"]alongsideforce_ipv4.gateway/run.py,cron/scheduler.py,hermes_cli/main.py: wireapply_ipv6_fallback_orderinginto the same blocks that callapply_ipv4_preference.ipv4_firstdefaults toTrue, so the fix is active out of the box.tests/test_ipv4_first.py: new test file mirroringtest_ipv4_preference.py— covers no-op when disabled, patching, double-patch safety, IPv4-first sorting ofAF_UNSPECresults, explicit-family pass-through, IPv6-only preservation, and config default.Relationship to #52538
PR #52538 (open) proposes auto-detection of dead IPv6 routes (probing + caching). This PR is a smaller-scope, immediately-shippable complement: it changes the default DNS ordering so IPv4 is tried first, which eliminates the timeout for the common case without the complexity of a detection/cache layer. The two approaches compose — if #52538 lands,
ipv4_firstcan become a fallback for when auto-detection is inconclusive, or be demoted to opt-in.Testing
pytest tests/test_ipv4_first.py tests/test_ipv4_preference.py -v→ 14 passed.