fix(api): keep unreachable content hosts out of the rendezvous rotation - #1016
fix(api): keep unreachable content hosts out of the rendezvous rotation#1016dylanjeffers wants to merge 1 commit into
Conversation
updateNodes built the rendezvous rotation straight from the on-chain registry. Registration says a node is entitled to serve content; it doesn't say the box is up. The only way to exclude a dead node was for a human to notice and ship a config.DeadNodes entry. audius.zeogrid.com hit that gap: refusing connections since at least 2026-08-11, still registered as validator Id 99, still in the rotation. It came back as the *primary* host on 9 of 25 sampled requests (36%) for gotamaX's cover photo, and ~8% of sampled trending artists had it in their host set. The blobs were fine — every affected image served 200 from its mirrors. Only the URL was bad, so the browser fell back to its cached copy and users reported their new profile picture or album art "reverting" on refresh, with the write having landed correctly. Support saw it as a data bug; it wasn't. The 1-minute nodesPoller now probes each registered node's /health_check and drops the ones that don't answer. Guards against the obvious ways this could make things worse: - A node must fail 3 consecutive probes (~3 min) before ejection, so a restart or a blip doesn't pull it out from under live traffic. - One success re-admits it and resets the count. - If ejecting would remove more than half the registry, the filter fails open and keeps everything. Most probes failing at once means this API's own network is the problem, and emptying the rotation would break every asset URL we serve. This also removes the need to hand-maintain config.DeadNodes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Don't love this change feels over engineered. We already have the store all hosts - why is it needed? |
|
You're right, and the premise I opened this on was wrong. Closing. I checked the client path I should have checked before filing. And your point about store-all is the load-bearing one: The one way this could still have bitten is that What I actually verified stands: zeogrid is down, still registered as validator Id 99, and came back as primary on 9 of 25 sampled requests. I just drew the wrong user-facing conclusion from it. #1017 is the one-liner adding it to Worth noting for the original support thread: this means the dead node never explained gotamaX. Their cover photo writes all landed and would have rendered via mirrors, and |
Diffing the eth registry (76) against core's non-jailed validator set (70) turns up six nodes core has already concluded are gone. All six fail to serve content: content.grassfed.network connection refused (already listed) audius.zeogrid.com connection refused cn0.mainnet.audiusindex.org 521 on health + content cn3.mainnet.audiusindex.org 521 on health + content cn4.mainnet.audiusindex.org 521 on health + content audius-nodes.com health_check 200, 502 on every content CID That last one is the interesting case: it passes a health check while serving nothing, so the active-probing approach in #1016 would have waved it through. Core's jailed flag caught it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
What's broken
updateNodesbuilds the rendezvous rotation straight from the on-chain registry. Registration says a node is entitled to serve content — it doesn't say the box is up. The only way to exclude a dead node today is for a human to notice and ship aconfig.DeadNodesentry.audius.zeogrid.comhas been sitting in that gap: refusing connections, still registered as validator Id 99, still in the rotation.Measured against prod on 2026-08-11:
Why this looked like a data bug
The blobs are fine. Every affected image serves
200from its mirrors — gotamaX changed their cover photo three times and all three writes landed correctly with distinct CIDs. Only the URL was bad, so the browser fell back to its cached copy and the user reported their new profile picture or album art "reverting" on refresh.This is one of two causes behind the current batch of "my profile photo keeps reverting" support reports. The other is a genuine write-path bug, fixed separately in OpenAudio/go-openaudio#510.
The fix
The existing 1-minute
nodesPollernow probes each registered node's/health_checkand drops the ones that don't answer.Guards against the obvious ways active health checking could make things worse:
This also removes the need to hand-maintain
config.DeadNodes.Tests
Six cases in
content_host_health_test.gocovering each guard: healthy nodes retained, ejection only after the threshold, re-admission on recovery with the counter reset, fail-open, empty registry, and deregistered endpoints being forgotten.Full
./api/suite passes (0 failures).TestSearchfails in my sandbox for want of Elasticsearch — verified identical on cleanmain, so unrelated.🤖 Generated with Claude Code