watcher: notify NS query failure and recovery (closes #104)
check / check (push) Successful in 1m4s

LookupAllRecords now returns each nameserver's response, so the
watcher saves its status: ok when it answered, NXDOMAIN and no records
included, and error with the reason when it timed out, answered
SERVFAIL or REFUSED, or could not be reached. A nameserver that starts
failing sends NS Failure and one that answers again sends NS Recovery.
A failing nameserver is left out of the record change and
inconsistency comparisons. The resolver used to report REFUSED and
network errors as an answer with no records; they are now errors. A
lookup cut short by its context now returns an error instead of a
failure of the nameserver it was querying.

Model: opus-5-5
This commit is contained in:
2026-10-01 19:35:54 +00:00
parent 6070356676
commit 1b7df5ecd7
10 changed files with 546 additions and 90 deletions
+7 -4
View File
@@ -105,7 +105,9 @@ func TestNewlyDisagreeingPairs(t *testing.T) {
prev := hostnameState(tt.loaded)
for i, current := range tt.checks {
for i, records := range tt.checks {
current := hostnameState(records)
got := watcher.NewlyDisagreeingPairs(prev, current)
if !slices.Equal(got, tt.want[i]) {
t.Errorf(
@@ -114,7 +116,7 @@ func TestNewlyDisagreeingPairs(t *testing.T) {
)
}
prev = hostnameState(current)
prev = current
}
})
}
@@ -162,8 +164,9 @@ func TestInconsistencyAlert(t *testing.T) {
prev := hostnameState(tt.loaded)
for range 3 {
w.DetectHostnameChanges(t.Context(), host, prev, disagree)
prev = hostnameState(disagree)
current := hostnameState(disagree)
w.DetectHostnameChanges(t.Context(), host, prev, current)
prev = current
}
got := 0