resolver, watcher: a record type whose query fails keeps its previous records (closes #231)
check / check (push) Canceled after 0s

The resolver lists in FailedTypes each record type whose query to a
nameserver got no usable reply: none after two tries, an error reply, a
referral, or a truncated reply whose TCP retry failed. Records holds
nothing for such a type, never none or the part that fit. A nameserver
that answered no type has failed, as before. The watcher keeps the
previous check's records for a failed type; when that check did not know
them either (first check, new or failing nameserver), the type is saved
in failedTypes and left out of record and inconsistency comparisons.
ResolveIPAddresses no longer counts a nameserver whose A, AAAA or CNAME
query failed as an answer.

Model: opus-5-5
This commit is contained in:
2026-10-02 06:00:30 +00:00
parent a18803ff28
commit 0ed7667ef5
13 changed files with 418 additions and 37 deletions
+19
View File
@@ -43,6 +43,25 @@ func TestCollectIPs_FailedIsNoAnswer(t *testing.T) {
assert.Empty(t, ips)
}
// TestCollectIPs_FailedTypeIsNoAnswer checks that a nameserver whose
// query for one of the types failed is no answer: its addresses are
// only part of them.
func TestCollectIPs_FailedTypeIsNoAnswer(t *testing.T) {
t.Parallel()
ips, _, err := resolver.CollectIPs(
map[string]*resolver.NameserverResponse{
nsExample1: {
Records: map[string][]string{"A": {"192.0.2.1"}},
FailedTypes: []string{"AAAA"},
Status: resolver.StatusOK,
},
},
)
require.ErrorIs(t, err, resolver.ErrNoNameserverAnswered)
assert.Empty(t, ips)
}
const (
// exampleCom is the zone most cases of TestUsableReply and
// TestNSSetFrom are about, and wwwExampleCom a name in it.