Skip to content

feat: negative-cache unreachable destinations and grow startup pre-warm#280

Merged
therealaleph merged 1 commit intotherealaleph:mainfrom
dazzling-no-more:perf/negative-cache-and-prewarm
Apr 26, 2026
Merged

feat: negative-cache unreachable destinations and grow startup pre-warm#280
therealaleph merged 1 commit intotherealaleph:mainfrom
dazzling-no-more:perf/negative-cache-and-prewarm

Conversation

@dazzling-no-more
Copy link
Copy Markdown
Contributor

Summary

Two small perf fixes driven by an Android log review.

1. Negative-cache unreachable destinations

On a device without IPv6, OS/app probes to IPv6-only hostnames (e.g. ds6.probe.whatismyipaddress.com) fail with Network is unreachable (os error 101). The probe gets retried every ~1.5s, and each retry was burning a fresh tunnel batch round-trip on a guaranteed failure — 5+ wasted sessions per probe in the logs.

TunnelMux now keeps a 30s, 256-entry negative cache keyed by (host, port). When the tunnel-node returns Network is unreachable / No route to host, the destination is remembered. The proxy front-end short-circuits subsequent CONNECTs:

  • HTTP CONNECT → 502 Bad Gateway
  • SOCKS5 CONNECT → reply 0x04 Host unreachable

Cache write rules (after review feedback):

  • Only writes from TunnelResponse.e — the tunnel-node's own connect result. Outer transport errors (relay → Apps Script never reached the tunnel-node) are never cached, so a momentary client-side WAN blip doesn't poison destinations.
  • Hard cap: prune-by-expiry first, then evict soonest-to-expire until under 256. The map can't grow unbounded during a unique-host burst.
  • Keys are normalized: lowercase + trailing-dot strip, so Example.COM.:443 and example.com:443 share an entry.

2. Bigger startup pre-warm pool

warm(3) was sized for one deployment. With multi-deployment configs, requests 4–10 of the opening burst paid a fresh TLS handshake each (~300ms). Now scales with deployment count: warm(num_scripts().clamp(6, 16)).

Test plan

  • cargo test --lib (143 passed)
  • New tests: error-string match, basic record/lookup, non-unreachable-skipped, host-key normalization, hard-cap under unique burst, outer-relay-error not cached

@dazzling-no-more dazzling-no-more changed the title perf: negative-cache unreachable destinations and grow startup pre-warm feat: negative-cache unreachable destinations and grow startup pre-warm Apr 26, 2026
@github-actions github-actions Bot added the type: feature feat: PR — auto-applied by release-drafter label Apr 26, 2026
@therealaleph therealaleph merged commit fa4e0fc into therealaleph:main Apr 26, 2026
2 checks passed
therealaleph added a commit that referenced this pull request Apr 26, 2026
#275: youtube_via_relay no longer routes video/image CDNs through
Apps Script. The flag now correctly carves out only the API/HTML
hosts where Restricted Mode is enforced; video chunks come direct
from googlevideo.com (which was missing from the SNI rewrite list
entirely — fixed). Long videos no longer hit Apps Script's 6-min
execution cap, and single-chunk timeouts no longer abort playback.

#280: TunnelMux now caches "destination unreachable" responses from
the tunnel-node (Network is unreachable / No route to host) for 30
seconds, short-circuiting subsequent CONNECTs to that destination
with 502 (HTTP) or 0x04 (SOCKS5). Saves ~5 batches/second on
IPv6-only host probes. Startup pre-warm pool grew 12→24.

143/143 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dazzling-no-more dazzling-no-more deleted the perf/negative-cache-and-prewarm branch April 26, 2026 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feature feat: PR — auto-applied by release-drafter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants