Files
mesh-sdk/go/catalogue/keyed.go
T
jschoubben 91aa7b78fc Key provisions by one rule the plan, the seat and the assigner share (issue 774)
The assigner's rule 8 waited for a key for every `requires`, while the plans named only the needs of handed modules:
every new build of grafana, dnsmasq, mesh-knowledge, mesh-mail and the builders waited for a key nobody would make,
and grafana, not handed, had no plan, so no route key and no route on route-proxy.

catalogue.Keyed is the rule (a need a module answers is keyed when its consumer is handed or the provider's helper
answers it), catalogue.Awaited the same rule from manifests for the assigner, and a module not handed now has a plan
for what a helper answers of it. Handed modules' plans are unchanged.

Quick fix: drop the missing-key check from rule 8. Thorough fix (chosen): one rule in mesh-sdk all three parts use,
since the kind (three parts deciding the same set apart) already drifted once and hid failures as waits.
2026-10-30 22:29:12 +01:00

68 lines
3.0 KiB
Go

package catalogue
import "slices"
// The one rule of which provisions the seat mesh-provisioner keys and a want waits for (novox/hq ADR 0570 §1, §2, §4;
// issue 774). The plan composition puts a need in a consumer's plan by it, the holder of mesh-provisioner keys what the
// plans name, and the assigner's rule 8 waits for what Awaited answers: three parts, one rule, so they cannot drift
// again (on 2026-10-30 the assigner waited for every `requires` while the plans named only some, and every new build of
// grafana, dnsmasq, mesh-knowledge, mesh-mail and the builders waited for a key nobody would make).
//
// A need a module answers (not a record, not nothing) is keyed when its consumer is handed to the provisioner, or the
// provider's offer says the provider helper answers it. A need of a consumer not handed whose provider's helper does
// not answer it is still answered by the controller's composition: it is neither keyed nor waited for.
// HandedByManifest is whether a module is handed to the provisioner as far as its manifest says (Rendering.Handing
// without the machine's own words, and begin's): marked moved, not a held module's stub, with a template its build
// kept or an item.
func (m Manifest) HandedByManifest() bool {
return m.Moved && m.Handed != nil && !m.Stubbed && (len(m.Handed.Templates) > 0 || len(m.Items) > 0)
}
// Keyed is whether a need is a provision of the seat mesh-provisioner: a key, an entry in its consumer's plan, and a
// wait of the consumer's want. consumerHanded is whether the composition hands the consumer to the provisioner.
func Keyed(consumerHanded bool, n Needed) bool {
if n.ByRecord || n.Module == "" || n.From == "" {
return false
}
return consumerHanded || n.AnsweredByHelper
}
// Awaited is, of what consumer requires (not optionally), each provision Keyed answers yes for, judged from manifests
// alone, as the assigner reads them: providers answers the modules providing a provision. A provision is a need when a
// provider offers it to the mesh, or one on the consumer's machine serves facts about it (Resolve: one answered on the
// machine with nothing served binds nothing). It is keyed when the consumer is handed, or every provider's offer is
// answered by the helper: where the providers disagree, which one answers is the composition's, and nothing is waited
// for that might never be keyed. Sorted, each once.
func Awaited(consumer Manifest, providers func(provision string) []Manifest) []string {
var out []string
for _, r := range consumer.Requires {
if consumer.OptionalRequires[r] || slices.Contains(out, r) {
continue
}
by := providers(r)
if len(by) == 0 {
continue
}
need, helper := false, true
for _, p := range by {
for _, o := range p.Provides {
if o.Name != r {
continue
}
if o.At() == ScopeMesh || len(p.Serves[r]) > 0 {
need = true
}
}
if !p.AnsweredByHelperFor(r) {
helper = false
}
}
if need && (consumer.HandedByManifest() || helper) {
out = append(out, r)
}
}
slices.Sort(out)
return out
}