Replay every unanimous upstream status, not just 4xx
openvoxdb does not reserve 5xx for its own faults: the same malformed query is a 400 on /nodes and a 500 on /facts, and /metrics answers a flat 403, so a 4xx-only replay rule made pdbmux's behaviour depend on the route. The meta and metrics handlers held their own copy of the gateway error and bypassed the replay entirely. - Replay any status from 400 up that every backend agreed on, with the backend's own body and content type. - Keep 502 for backends disagreeing on the status, or a backend that answered nothing at all. - Route /pdb/meta, /metrics and the pass-through path through the same rule as the merged query handlers. - Count a unanimous 5xx as a failed round and let it fall back to a stale cache entry; only a unanimous 4xx stays exempt from both. - Answer successful queries with openvoxdb's application/json;charset=utf-8.
This commit is contained in:
@@ -72,8 +72,10 @@ func (s *Server) rawBackend(ctx context.Context, b Backend, path, rawQuery strin
|
||||
}
|
||||
}
|
||||
|
||||
// aliveRaw drops backends that errored or answered non-2xx, writing a 502 and
|
||||
// returning ok=false only when none is left.
|
||||
// aliveRaw drops backends that errored or answered non-2xx, returning ok=false
|
||||
// when none is left. The reply it writes then is the same one the merged query
|
||||
// handlers write, so /pdb/meta and /metrics answer a failure exactly as
|
||||
// /pdb/query does: a unanimous upstream error replayed, anything else a 502.
|
||||
func (s *Server) aliveRaw(w http.ResponseWriter, results []rawResult, path string) ([]rawResult, bool) {
|
||||
var alive []rawResult
|
||||
for _, res := range results {
|
||||
@@ -84,12 +86,25 @@ func (s *Server) aliveRaw(w http.ResponseWriter, results []rawResult, path strin
|
||||
alive = append(alive, res)
|
||||
}
|
||||
if len(alive) == 0 {
|
||||
http.Error(w, "all backends failed", http.StatusBadGateway)
|
||||
s.writeUpstreamError(w, upstreamOutcome(rawUpstreamErrors(results)))
|
||||
return nil, false
|
||||
}
|
||||
return alive, true
|
||||
}
|
||||
|
||||
// rawUpstreamErrors reduces a raw fan-out to one entry per backend, nil where
|
||||
// the backend answered 2xx or never answered at all.
|
||||
func rawUpstreamErrors(results []rawResult) []*upstreamError {
|
||||
errs := make([]*upstreamError, len(results))
|
||||
for i, res := range results {
|
||||
if res.err != nil || res.ok() {
|
||||
continue
|
||||
}
|
||||
errs[i] = newUpstreamError(res.status, res.contentType, res.body)
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r rawResult) reason() string {
|
||||
if r.err != nil {
|
||||
return r.err.Error()
|
||||
|
||||
Reference in New Issue
Block a user