plugin/cache: Fix timed stale caused refreshes (#8587)

This commit is contained in:
Yong Tang
2026-09-30 01:18:21 -07:00
committed by GitHub
parent 9fbbdd2698
commit 8f7b2a66ea
2 changed files with 45 additions and 4 deletions

View File

@@ -54,7 +54,7 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
if c.verifyStale {
failureRecheck := c.staleRecheck
nowFunc := c.now
trackRefresh := failureRecheck > 0
trackRefresh := failureRecheck > 0 || c.verifyStaleTimeout > 0
if !trackRefresh || i.beginRefresh(now, failureRecheck) {
refreshState := authenticatedRefreshState(state)
crr := &ResponseWriter{ResponseWriter: w, Cache: c, state: refreshState, server: server, do: do, ad: ad, cd: cd}
@@ -187,9 +187,7 @@ func (c *Cache) verifyWithTimeout(ctx context.Context, state request.Request, w
}
go func() {
rc, re := c.doRefresh(refreshCtx, state, cw)
if failureRecheck > 0 {
i.endRefresh(now(), failureRecheck, cw.refreshed)
}
i.endRefresh(now(), failureRecheck, cw.refreshed)
done <- result{rc, re}
}()
timer := time.NewTimer(c.verifyStaleTimeout)

View File

@@ -299,6 +299,49 @@ func TestServeStaleFailureRecheckVerifyTimeoutCoalesces(t *testing.T) {
}
}
func TestServeStaleVerifyTimeoutCoalescesWithoutFailureRecheck(t *testing.T) {
clock := newStaleRecheckClock()
c := New()
c.now = clock.Now
c.minpttl = 0
c.minnttl = 0
c.staleUpTo = time.Hour
c.verifyStale = true
c.verifyStaleTimeout = 10 * time.Millisecond
c.Next = ttlBackend(1)
req := new(dns.Msg)
req.SetQuestion("cached.org.", dns.TypeA)
serveStaleRecheckRequest(t, c, req)
item := c.exists("cached.org.", dns.TypeA, dns.ClassINET, false, false)
clock.Set(2 * time.Second)
var calls atomic.Int32
started := make(chan struct{}, 2)
completed := make(chan struct{}, 2)
release := make(chan struct{})
defer close(release)
failure := servFailBackend(30)
c.Next = plugin.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
calls.Add(1)
started <- struct{}{}
<-release
rcode, err := failure.ServeDNS(ctx, w, r)
completed <- struct{}{}
return rcode, err
})
serveStaleRecheckRequest(t, c, req)
waitForStaleSignal(t, started, "background verify did not start")
serveStaleRecheckRequest(t, c, req)
if got := calls.Load(); got != 1 {
t.Fatalf("expected concurrent stale request to share the in-flight verify, got %d attempts", got)
}
release <- struct{}{}
waitForStaleRefresh(t, completed, item)
}
func TestServeStaleFailureRecheckDisabledPreservesVerifyBehavior(t *testing.T) {
clock := newStaleRecheckClock()
c := New()