Files
cedricandClaude Opus 5.5 3504263992 Disk buffer for batches VictoriaLogs cannot take, lossless Docker positions, non-blocking reverse DNS
- Batches that fail go to /data/spool (SPOOL_MAX_MB, 1 GiB by default) and
  are sent again oldest first; retries no longer block the store loop and
  follow the shutdown context.
- Docker and host logs wait for room in a full queue instead of being
  dropped; the Docker position only moves once a line is stored or spooled.
- Reverse DNS no longer holds up the syslog listeners, with an LRU cache
  and a cap on concurrent lookups.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-03 16:26:18 +02:00

78 lines
2.0 KiB
Go

package main
import (
"context"
"errors"
"net"
"testing"
"time"
)
// slowDNS never answers before the context ends.
func slowDNS() *ReverseDNS {
d := NewReverseDNS(true, "")
d.r = &net.Resolver{PreferGo: true, Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
<-ctx.Done()
return nil, errors.New("timeout")
}}
return d
}
func TestResolveDoesNotBlock(t *testing.T) {
d := slowDNS()
got := make(chan string, 1)
start := time.Now()
d.Resolve("192.0.2.1", 50*time.Millisecond, func(name string) { got <- name })
if time.Since(start) > 20*time.Millisecond {
t.Fatal("Resolve waited for the DNS server")
}
if name := <-got; name != "" {
t.Errorf("name %q, want none", name)
}
// Not an IP address: the callback runs at once.
called := false
d.Resolve("router", time.Second, func(name string) { called = name == "" })
if !called {
t.Error("callback not called synchronously for a host name")
}
}
func TestReverseDNSLimits(t *testing.T) {
d := slowDNS()
// Lookups beyond the limit are not started (and not cached).
for i := 0; i < rdnsMaxLookups+10; i++ {
d.Lookup(net.IPv4(10, 0, byte(i>>8), byte(i)).String(), 0)
}
if n := d.lru.Len(); n != rdnsMaxLookups {
t.Errorf("%d entries, want %d", n, rdnsMaxLookups)
}
}
func TestReverseDNSEvictsLeastRecentlyUsed(t *testing.T) {
d := slowDNS()
done := make(chan struct{})
close(done)
add := func(ip string) {
e := &rdnsEntry{ip: ip, name: ip + ".lan", expires: time.Now().Add(time.Hour), done: done}
d.cache[ip] = d.lru.PushFront(e)
}
for i := 0; i < rdnsMaxEntries; i++ {
add(net.IPv4(10, 1, byte(i>>8), byte(i)).String())
}
first := net.IPv4(10, 1, 0, 0).String()
if name := d.Lookup(first, 0); name != first+".lan" { // now the most recent
t.Fatalf("cached name %q", name)
}
d.entry("192.0.2.9")
if d.lru.Len() != rdnsMaxEntries {
t.Errorf("%d entries, want %d", d.lru.Len(), rdnsMaxEntries)
}
if d.cache[first] == nil {
t.Error("recently used entry evicted")
}
if d.cache[net.IPv4(10, 1, 0, 1).String()] != nil {
t.Error("least recently used entry kept")
}
}