fix data races in cache, resolver, qlog; add cache/zonefile/blocklist tests; update STATUS

- cache.Entry.Hits and LRU.perShard become atomics; SetCapacity now evicts
  down to the new budget; packKey fully qualifies names before packing
- resolver.Pool rewritten copy-on-write (atomic.Pointer to an immutable
  state); Upstream is immutable with shared *upstreamStats, so health
  survives a Rebind and the query path stops racing the config hook
- Pool.Exchange no longer marks a dead upstream healthy: Success was
  called before the error check, so the breaker never tripped
- qlog live ring publishes through atomic pointers
- blocklist.Holder.Get nil-safe; Builder lists each source once
- web: fix toast(string) misuse that rendered empty mutation toasts
- add unit tests for cache (with benchmarks) and zonefile
- STATUS.md: green -race integration suite, remaining failures and the
  broken bbolt snapshot round trip documented
This commit is contained in:
developer committed 2026-09-27 12:59:02 +00:00
1 parent 10e8a9b91a
commit aa12b03eb9
7 files changed
+228 -144

No files matched your search

+34 -14
View File
@@ -214,13 +214,16 @@ type SourceMeta struct {
// Builder accumulates rules and produces a Set.
type Builder struct {
exact map[string]*Entry
sub map[string]*Entry
root map[string]*Entry
meta map[string]SourceMeta
order []string
dup int
counts RuleCounts
exact map[string]*Entry
sub map[string]*Entry
root map[string]*Entry
meta map[string]SourceMeta
order []string
// ordered mirrors order, so a source is listed once even when both a rule
// and its metadata mention it.
ordered map[string]bool
dup int
counts RuleCounts
}
// NewBuilder returns an empty Builder.
@@ -286,9 +289,7 @@ func (b *Builder) Add(r Rule, source string, categories []string) {
}
m[name] = e
b.countAction(e, 1)
if _, seen := b.meta[source]; !seen {
b.order = append(b.order, source)
}
b.noteOrder(source)
}
// metaFor reports whether a source already contributed to this build.
@@ -326,12 +327,25 @@ func (b *Builder) uncount(e *Entry) {
// NoteSource records (or updates) bookkeeping for a contributing source.
func (b *Builder) NoteSource(meta SourceMeta) {
if _, seen := b.meta[meta.Name]; !seen {
b.order = append(b.order, meta.Name)
}
b.noteOrder(meta.Name)
b.meta[meta.Name] = meta
}
// noteOrder appends a source to the build order exactly once.
func (b *Builder) noteOrder(name string) {
if name == "" {
return
}
if b.ordered == nil {
b.ordered = make(map[string]bool, 16)
}
if b.ordered[name] {
return
}
b.ordered[name] = true
b.order = append(b.order, name)
}
// SourceCount is the number of contributing sources.
func (b *Builder) SourceCount() int { return len(b.meta) }
@@ -731,7 +745,13 @@ func NewHolder(s *Set) *Holder {
}
// Get returns the current set (nil before the first build).
func (h *Holder) Get() *Set { return h.cur.Load() }
// Get returns the current set, or nil when nothing has been compiled yet.
func (h *Holder) Get() *Set {
if h == nil {
return nil
}
return h.cur.Load()
}
// Set installs a new set.
func (h *Holder) Set(s *Set) { h.cur.Store(s) }