agent/endpoint: Manifest.Version() digest for skew detection

Order-independent fnv64a of the route set so a multi-node layer can tell
whether the nodes serving a deployment agree on the manifest (safe to route
without inspecting the path) or are mid rolling-deploy (fall back to a
path-aware resolve).
This commit is contained in:
Théo Monnom
2026-08-20 14:40:12 -07:00
parent caf261ac47
commit e4fecfb4cb
+23
View File
@@ -16,7 +16,9 @@ package endpoint
import (
"fmt"
"hash/fnv"
"slices"
"strconv"
"strings"
"github.com/livekit/protocol/livekit"
@@ -37,6 +39,27 @@ type Manifest struct {
routes []Route
}
// Version is a stable fnv64a digest of the route set, used to detect manifest
// skew across nodes serving the same deployment (all-agree => safe to route
// without inspecting the path). It is order-independent: two workers on the
// same revision hash identically regardless of route declaration order.
func (m *Manifest) Version() uint64 {
lines := make([]string, 0, len(m.routes))
for i := range m.routes {
r := &m.routes[i]
methods := append([]string(nil), r.Methods...)
slices.Sort(methods)
lines = append(lines, strconv.Itoa(int(r.Kind))+" "+r.Template.String()+" "+strings.Join(methods, ",")+" "+strconv.FormatBool(r.Public))
}
slices.Sort(lines)
h := fnv.New64a()
for _, l := range lines {
_, _ = h.Write([]byte(l))
_, _ = h.Write([]byte{0})
}
return h.Sum64()
}
// MatchResult mirrors starlette's Match enum: a FULL match selects the route, a
// PARTIAL match (path matched, method didn't) yields 405 only after the whole
// table has been scanned, so a later route with the right method still wins.