Answer the review of hq issues 348 and 349: gaps, parts, the newest merge in any state
- A reopened fault keeps its gaps: it was there at a send unless the send fell in one, so a send that breaks a machine recovered before it still fails its gate (A2). - An undecided part holds only the conditions that name it (A4). - D2 holds a silent resolver for the next run again, refused or not: a burst of refusals is also a restart (A3). - A late merge is planned at the newest planned merge of its branch in any state, not only an open one (A1); merge times to the nanosecond (A5).
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
@@ -217,8 +216,6 @@ func askEveryResolver(ctx context.Context, resolvers map[string]string, places [
|
||||
type verdict struct {
|
||||
wrong, unanswered, said []string
|
||||
asked int
|
||||
// refused says every try of every unanswered question was refused (nothing listens there).
|
||||
refused bool
|
||||
}
|
||||
byHolder := map[string]*verdict{}
|
||||
for _, q := range questions {
|
||||
@@ -235,7 +232,6 @@ func askEveryResolver(ctx context.Context, resolvers map[string]string, places [
|
||||
v.wrong = append(v.wrong, words)
|
||||
v.said = append(v.said, said)
|
||||
default:
|
||||
v.refused = (len(v.unanswered) == 0 || v.refused) && q.asked.allRefused()
|
||||
v.unanswered = append(v.unanswered, words)
|
||||
v.said = append(v.said, said)
|
||||
}
|
||||
@@ -255,11 +251,12 @@ func askEveryResolver(ctx context.Context, resolvers map[string]string, places [
|
||||
o.Summary = fmt.Sprintf("the mesh's resolver on %s does not answer machine names as it must: %s%s", node,
|
||||
v.wrong[0], andMore(len(v.wrong)-1))
|
||||
} else {
|
||||
// Nothing but silence: held for the next run, which raises it if the resolver is still silent —
|
||||
// unless every try of every question was refused. A refusal is an answer from the machine:
|
||||
// nothing listens there. It is not a loaded resolver slow to answer (issue 277), and holding it
|
||||
// for the next run cost the control node's resolver five minutes on 2026-10-09 (issue 348).
|
||||
o.Confirm = !v.refused
|
||||
// Nothing but silence: held for the next run, which raises it if the resolver is still silent.
|
||||
// Refused on every try too: a few hundred milliseconds of refusals is a resolver restarting as
|
||||
// well as one that stopped, and the two looks a finding needs are this run and the next
|
||||
// (novox/hq issue 348). The machine's own node-engine is the fast detector: its names check
|
||||
// raised the control node's resolver within a minute on 2026-10-09.
|
||||
o.Confirm = true
|
||||
o.Summary = fmt.Sprintf("the mesh's resolver on %s does not answer: %d of the %d question(s) about the "+
|
||||
"machines' names went unanswered, each asked %d times — the first, %s", node, len(v.unanswered), v.asked,
|
||||
resolverTries, v.unanswered[0])
|
||||
@@ -348,19 +345,6 @@ type resolverAsked struct {
|
||||
errs []error
|
||||
}
|
||||
|
||||
// allRefused says every try was refused: the resolver's machine said nothing listens on its port.
|
||||
func (a resolverAsked) allRefused() bool {
|
||||
if a.answered || len(a.errs) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, err := range a.errs {
|
||||
if !errors.Is(err, syscall.ECONNREFUSED) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// askResolverPatiently asks one question until it is answered as right says, at most resolverTries
|
||||
// times. A wrong answer is asked again too — a resolver restarting may say NXDOMAIN for a moment — and
|
||||
// stands if no try answers rightly.
|
||||
|
||||
Reference in New Issue
Block a user