package pipeline import ( mathrand "math/rand/v2" "sync" ) // stringSample is a memory-bounded queue that keeps a random sample of recent // hostnames instead of a FIFO. A FIFO fills with the first N hostnames seen at // startup and drops everything after, so DNS enrichment only ever sees stale // hostnames and CNAME discovery stalls. Random replacement makes coverage // representative at bounded memory. Not on the certificate hot path. type stringSample struct { mu sync.Mutex items []string cap int notify chan struct{} stop chan struct{} once sync.Once } func newStringSample(capacity int) *stringSample { return &stringSample{ cap: capacity, notify: make(chan struct{}, 1), stop: make(chan struct{}), } } func (q *stringSample) push(s string) { q.mu.Lock() if len(q.items) < q.cap { q.items = append(q.items, s) } else { q.items[mathrand.IntN(len(q.items))] = s } q.mu.Unlock() select { case q.notify <- struct{}{}: default: } } func (q *stringSample) pop() (string, bool) { q.mu.Lock() n := len(q.items) if n == 0 { q.mu.Unlock() return "", false } i := mathrand.IntN(n) s := q.items[i] q.items[i] = q.items[n-1] q.items = q.items[:n-1] q.mu.Unlock() return s, true } func (q *stringSample) len() int { q.mu.Lock() defer q.mu.Unlock() return len(q.items) } func (q *stringSample) close() { q.once.Do(func() { close(q.stop) }) select { case q.notify <- struct{}{}: default: } }