Files
mesh-delivery/modules/mesh-delivery-builder/internal/build/choose.go
T

64 lines
2.1 KiB
Go

package build
import (
"fmt"
"sort"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// ChooseNodes picks up to want build nodes for a language (ADR 0478 clause 3): the nodes whose toolchains key reports the
// version the nodes agree on, the ones with the fewest steps the builder has running there first, a tie broken by the
// node's name. It answers the toolchain they agree on. When nothing is reported, or the nodes report different versions
// (so the indexer agreed none), it fails naming the language and why. The build module's health is not read here: a node
// whose module refuses on its toolchain refuses the step, and the build fails naming it.
func ChooseNodes(language string, entries []delivery.NodeToolchain, running map[string]int, want int) ([]string, delivery.Toolchain2, error) {
tc, none := delivery.AgreedToolchain(entries)
if none != "" {
return nil, delivery.Toolchain2{}, fmt.Errorf("no %s build node qualifies: %s", language, none)
}
nodes := make([]string, 0, len(entries))
seen := map[string]bool{}
for _, e := range entries {
if !seen[e.Node] {
seen[e.Node] = true
nodes = append(nodes, e.Node)
}
}
sort.Slice(nodes, func(i, j int) bool {
if running[nodes[i]] != running[nodes[j]] {
return running[nodes[i]] < running[nodes[j]]
}
return nodes[i] < nodes[j]
})
if len(nodes) > want {
nodes = nodes[:want]
}
return nodes, tc, nil
}
// Agree is the one digest every node built an artifact to (ADR 0478 clause 4), or an error naming each node and its
// digest when they differ. One node's digest agrees with itself.
func Agree(artifact string, byNode map[string]string) (string, error) {
nodes := make([]string, 0, len(byNode))
for n := range byNode {
nodes = append(nodes, n)
}
sort.Strings(nodes)
var first string
for i, n := range nodes {
if i == 0 {
first = byNode[n]
continue
}
if byNode[n] != first {
msg := fmt.Sprintf("the nodes built %s to different digests:", artifact)
for _, n := range nodes {
msg += fmt.Sprintf(" %s %s;", n, byNode[n])
}
return "", fmt.Errorf("%s", msg[:len(msg)-1])
}
}
return first, nil
}