Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь. Co-authored-by: Cursor <[email protected]>
70 lines
1.6 KiB
Go
70 lines
1.6 KiB
Go
package store
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"sort"
|
|
)
|
|
|
|
// PrefixSnapshotHash is the content key of prefix_snapshot.
|
|
// It fingerprints prefix rows only. Peer configuration stays on
|
|
// config_revision.content_hash so a peer-only change can reuse the snapshot.
|
|
// The result is 64 lowercase hex characters. Row order does not affect the hash.
|
|
func PrefixSnapshotHash(rows []PrefixRow) string {
|
|
cp := append([]PrefixRow(nil), rows...)
|
|
sortPrefixRows(cp)
|
|
h := sha256.New()
|
|
for _, row := range cp {
|
|
_, _ = h.Write([]byte(row.Prefix))
|
|
_, _ = h.Write([]byte{1})
|
|
if row.CommunityID == nil {
|
|
_, _ = h.Write([]byte{0})
|
|
} else {
|
|
_, _ = h.Write([]byte{1})
|
|
_, _ = h.Write([]byte(*row.CommunityID))
|
|
}
|
|
_, _ = h.Write([]byte{1})
|
|
_, _ = h.Write([]byte(row.Source))
|
|
_, _ = h.Write([]byte{0})
|
|
}
|
|
sum := h.Sum(nil)
|
|
return hex.EncodeToString(sum)
|
|
}
|
|
|
|
func sortPrefixRows(rows []PrefixRow) {
|
|
sort.Slice(rows, func(i, j int) bool {
|
|
if rows[i].Prefix != rows[j].Prefix {
|
|
return rows[i].Prefix < rows[j].Prefix
|
|
}
|
|
ni, vi := communitySortKey(rows[i].CommunityID)
|
|
nj, vj := communitySortKey(rows[j].CommunityID)
|
|
if ni != nj {
|
|
return ni
|
|
}
|
|
if vi != vj {
|
|
return vi < vj
|
|
}
|
|
return rows[i].Source < rows[j].Source
|
|
})
|
|
}
|
|
|
|
func communitySortKey(id *string) (isNil bool, val string) {
|
|
if id == nil {
|
|
return true, ""
|
|
}
|
|
return false, *id
|
|
}
|
|
|
|
func samePrefixRow(a, b PrefixRow) bool {
|
|
if a.Prefix != b.Prefix || a.Source != b.Source {
|
|
return false
|
|
}
|
|
if (a.CommunityID == nil) != (b.CommunityID == nil) {
|
|
return false
|
|
}
|
|
if a.CommunityID != nil && *a.CommunityID != *b.CommunityID {
|
|
return false
|
|
}
|
|
return true
|
|
}
|