Merge main into benvin/drop-fact-caching
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful

Both sides added jsonContentType; keep one. The no-entry 502 test kills the
backends outright, since main replays a unanimous 500, and the cached
content-type test moves to /nodes, the only cached path left.
This commit is contained in:
2026-09-13 14:54:08 +10:00
13 changed files with 708 additions and 137 deletions
+13 -3
View File
@@ -61,6 +61,7 @@ type countingBackend struct {
hits map[string]int
bodies map[string]string
fail bool
dead bool
block chan struct{}
}
@@ -70,12 +71,15 @@ func newCountingBackend(t *testing.T, bodies map[string]string) *countingBackend
cb.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cb.mu.Lock()
cb.hits[r.URL.Path]++
fail, block, body := cb.fail, cb.block, cb.bodies[r.URL.Path]
fail, dead, block, body := cb.fail, cb.dead, cb.block, cb.bodies[r.URL.Path]
cb.mu.Unlock()
if block != nil {
<-block
}
if dead {
panic(http.ErrAbortHandler)
}
if fail {
http.Error(w, "boom", http.StatusInternalServerError)
return
@@ -108,6 +112,12 @@ func (cb *countingBackend) totalHits() int {
return n
}
func (cb *countingBackend) setDead(v bool) {
cb.mu.Lock()
defer cb.mu.Unlock()
cb.dead = v
}
func (cb *countingBackend) setFail(v bool) {
cb.mu.Lock()
defer cb.mu.Unlock()
@@ -355,8 +365,8 @@ func TestHandler_ServesStaleOnlyWhenBackendsFail(t *testing.T) {
func TestHandler_NoCacheEntryMeansBackendFailureIs502(t *testing.T) {
a := newCountingBackend(t, map[string]string{nodesPath: `[]`})
b := newCountingBackend(t, map[string]string{nodesPath: `[]`})
a.setFail(true)
b.setFail(true)
a.setDead(true)
b.setDead(true)
srv, _ := newCachedServer(t, cacheTestConfig(a.srv.URL, b.srv.URL))
rec := doGet(t, srv.Handler(), nodesPath, "")