Skip to content

fix(bitswap/httpnet): bound probe traffic - #1205

Merged
gammazero merged 5 commits into
mainfrom
fix/httpnet-bound-probe-traffic
Aug 17, 2026
Merged

fix(bitswap/httpnet): bound probe traffic#1205
gammazero merged 5 commits into
mainfrom
fix/httpnet-bound-probe-traffic

Conversation

@lidel

@lidel lidel commented Aug 16, 2026

Copy link
Copy Markdown
Member

Problem

For legacy reasons, every connected HTTP peer gets probed with GET/HEAD /ipfs/bafkqaaa every 5 seconds for the lifetime of the process. Results are discarded, failures never slow the loop, and Connect re-probes failing endpoints with no memory. A single idle daemon emits ~17k requests per day per HTTP provider. The probe target and wire format are spec-defined and unchanged1; the defect is frequency and lifecycle, which the spec does not constrain.

Fix

  • delete the ping loop; latency for the DONT_HAVE timeout manager is seeded from the Connect probe round trip and updated from time-to-headers of server-understood retrieval responses; on-demand Ping stays, matching bsnet
  • Connect and Ping honor per-host cooldowns; a failed probe starts one from Retry-After23 (past dates rejected) or the new DefaultConnectFailureBackoff; endpoints skipped for an active cooldown stay in the peerstore as failover targets
  • cooldowns move to a process-wide SharedCooldownTracker so backoff survives applications that build a short-lived Network per retrieval; WithCooldownTracker opts a Network out; the tracker holds no goroutine and needs no shutdown
  • expired sender cooldown snapshots no longer poison a sender for its lifetime, and the 410 probe workaround for a provider that shut down is gone

Historic conxtex: the 5s interval landed in #747 without a stated rationale, nothing consumes it on a schedule, and #918 already records that idle peers should not be pinged. An opt-in periodic pinger can come back later without API breakage, but i'm unsure we need it..

Testing

New synctest and integration suites cover the behavior changes; TestNoBackgroundProbes is the regression guard for the removed loop. go test -race -count=3 ./bitswap/network/httpnet/... and go test -race ./bitswap/... pass. Companion kubo PR (branch pinned, green CI) plus ipfs-check and rainbow validation branches: to follow, linked here before merge.

Before this ships as a patch release, we need to make sure success rate remains the same:

Footnotes

  1. Trustless Gateway spec, dedicated probe paths: defines the probe target and response; says nothing about client request frequency.

  2. Path Gateway spec, Retry-After response header: gateways SHOULD return Retry-After with 429, 503 and 504.

  3. RFC 9110, section 10.2.3: Retry-After indicates how long the user agent ought to wait before making a follow-up request.

lidel added 3 commits August 16, 2026 19:44
Every connected HTTP peer was probed with GET/HEAD /ipfs/bafkqaaa every
5 seconds for the lifetime of the process, with results discarded and no
backoff; at fleet scale this generated tens of thousands of requests per
second of background load on public gateways. Latency, whose only
scheduled consumer is the DONT_HAVE timeout manager, is now measured
without dedicated traffic:

- seed the EWMA from the Connect probe round trip
- update it from time-to-headers of server-understood retrieval
  responses (200 and the 404 family); throttle and server errors are
  excluded so they cannot shrink DONT_HAVE timeouts
- keep on-demand Ping for interface compliance
- the pinger struct remains as the connection registry backing
  IsConnectedToPeer; latency is still wiped on disconnect
Connect re-probed failing endpoints on every call with no memory, and
a message sender created during a cooldown treated it as permanent.
Backoff now works end to end:

- Connect and Ping honor per-host cooldowns; a failed probe starts one
  from Retry-After (past dates rejected) or the new exported
  DefaultConnectFailureBackoff
- endpoints skipped only for an active cooldown stay in the peerstore
  as failover targets instead of being lost for the connection's
  lifetime; HEAD support is not assumed for them
- cooldowns live in a process-wide SharedCooldownTracker by default so
  they survive short-lived Network instances; WithCooldownTracker opts
  a Network into a private registry; Network.Stop leaves the registry
  alone; the tracker no longer runs a cleaner goroutine (expired
  entries are swept during writes)
- expired sender cooldown snapshots are cleared (CompareAndSwap, so a
  concurrently stored fresh deadline survives) instead of poisoning
  the sender for its lifetime
410 on the connection probe counted as success to accommodate a
provider that has since shut down. A 410 probe now fails Connect and
starts a cooldown; 410 on real block requests still counts as a valid
content-unavailable reply.
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.78102% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.20%. Comparing base (f75e524) to head (8d1234e).

Files with missing lines Patch % Lines
bitswap/network/httpnet/pinger.go 79.06% 8 Missing and 1 partial ⚠️
bitswap/network/httpnet/httpnet.go 90.00% 4 Missing and 1 partial ⚠️

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1205      +/-   ##
==========================================
+ Coverage   63.85%   64.20%   +0.34%     
==========================================
  Files         269      269              
  Lines       27148    27193      +45     
==========================================
+ Hits        17335    17458     +123     
+ Misses       8096     8018      -78     
  Partials     1717     1717              
Files with missing lines Coverage Δ
bitswap/network/httpnet/cooldown.go 100.00% <100.00%> (+34.61%) ⬆️
bitswap/network/httpnet/msg_sender.go 64.74% <100.00%> (+3.88%) ⬆️
bitswap/network/httpnet/httpnet.go 68.84% <90.00%> (+5.98%) ⬆️
bitswap/network/httpnet/pinger.go 63.15% <79.06%> (+26.59%) ⬆️

... and 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gammazero gammazero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Only a few nits, mostly not even part of your PR, that changing is optional.

Comment thread bitswap/network/httpnet/pinger.go
Comment thread bitswap/network/httpnet/pinger.go
Comment thread bitswap/network/httpnet/httpnet.go Outdated
jsamol pushed a commit to Acurast/ipfs-mobile that referenced this pull request Aug 17, 2026
pseudo-version of ipfs/boxo#1205; removes the 5s ping loop, adds probe
backoff with Retry-After, and keeps cooldowns in a process-wide registry
that survives node-per-download recycling
acurastgitlab pushed a commit to Acurast/ipfs-mobile that referenced this pull request Aug 17, 2026
pseudo-version of ipfs/boxo#1205; removes the 5s ping loop, adds probe
backoff with Retry-After, and keeps cooldowns in a process-wide registry
that survives node-per-download recycling

(cherry picked from commit b43e2dc)
lidel and others added 2 commits August 17, 2026 11:04
Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com>
TestDisconnectFreezesProbes failed on windows runners: their monotonic
clock ticks at ~0.5ms, so a probe over a pooled connection measures as
zero and the reconnect latency seed was skipped, making a measured
peer look unmeasured. Latency samples are now floored at 1ms in
recordLatencyIfConnected and Connect seeds unconditionally, since
seeding is only reached after a successful probe. The test covers the
zero-sample case.
@lidel
lidel force-pushed the fix/httpnet-bound-probe-traffic branch from 5bec5a5 to 8d1234e Compare August 17, 2026 10:41
@lidel

lidel commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

@gammazero fwiw staging test looks ok: https://github.com/ipshipyard/waterworks-infra/pull/1037#issuecomment-5313945021 -- if no concerns, feel free to merge and ship as a patch release (fine if its the only fix, we want this out asap, just so LLMs stop propagating older version)

@gammazero
gammazero merged commit d8b6157 into main Aug 17, 2026
26 checks passed
@gammazero
gammazero deleted the fix/httpnet-bound-probe-traffic branch August 17, 2026 11:00
@lidel
lidel restored the fix/httpnet-bound-probe-traffic branch August 17, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants