diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go index 1be4b2b..73371a2 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go @@ -58,7 +58,6 @@ func main() { var readBuckets = []string{ buscompose.ResolvedBucket, delivery.PartGrantsBucket, - delivery.ControllerComposedBucket, delivery.AnswersBucket, delivery.BuilderBuildsBucket, delivery.CandidatesBucket, @@ -296,7 +295,6 @@ func (e emitting) Emit(eventType string, body any) error { return e.Conn.Emit(ev var watched = []string{ buscompose.ResolvedBucket, delivery.PartGrantsBucket, - delivery.ControllerComposedBucket, delivery.AnswersBucket, delivery.BuilderBuildsBucket, delivery.CandidatesBucket, diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seat_tools_test.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seat_tools_test.go index 70035f2..8c72782 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seat_tools_test.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seat_tools_test.go @@ -339,7 +339,7 @@ func TestTheSeatsVerbs(t *testing.T) { func wantsVerbs(t *testing.T) { fpOld, fpNew := delivery.SourcePrefix2+strings.Repeat("1", 64), delivery.SourcePrefix2+strings.Repeat("2", 64) st := memStore{} - for _, state := range []string{modulesState, manifestsState, composedState, policiesState, haveState, putsState, "findings"} { + for _, state := range []string{modulesState, manifestsState, policiesState, haveState, putsState, "findings"} { st[state] = &memKV{values: map[string][]byte{}} } manifest := func(name, extra string) { @@ -354,13 +354,7 @@ func wantsVerbs(t *testing.T) { for node, fp := range map[string]string{"anchor": fpOld, "laptop": fpNew} { st[haveState].values[node+".nats"], _ = delivery.EncodeHave(delivery.Have{FP: fp, Phase: delivery.PhaseRunning, Health: delivery.HealthOK}) } - composed := func(module, policy string) { - key, _ := delivery.ComposedKey("anchor", module, fpNew) - st[composedState].values[key], _ = json.Marshal(delivery.ComposedDigest{V: delivery.Version, Digest: "sha256:" + strings.Repeat("c", 64), - Judgement: delivery.JudgedNeither, Policy: policy, PolicyFrom: catalogue.FromPerson, PolicyWhy: "chosen at the controller"}) - } - composed("web", catalogue.PolicyRecord) - composed("photos", catalogue.PolicyRecord) + st[haveState].values["anchor.node"], _ = delivery.EncodeHaveNode(delivery.HaveNode{Composed: "sha256:" + strings.Repeat("c", 64)}) var asked []string var said []string w := newWantsTools(st, func(key string, body any) (json.RawMessage, error) { @@ -380,10 +374,11 @@ func wantsVerbs(t *testing.T) { if p := policyOf("nats"); p.Policy != catalogue.PolicyRecord || p.From != catalogue.FromBus { t.Errorf("nats = %+v", p) } - // compare: web rolls at the assigner and records at the controller. + // compare: the controller writes no policy, so no module splits; each node's own composition is the digest its have names. out, _ := w.doUpgrade(map[string]any{"compare": "true"}, "op") - if splits := out.(map[string]any)["splits"].([]assign.Split); len(splits) != 1 || splits[0].Module != "web" || out.(map[string]any)["findings"] == nil { - t.Errorf("splits = %+v", splits) + if got := out.(map[string]any); len(got["splits"].([]assign.Split)) != 0 || got["empty"] != true || got["findings"] == nil || + got["composed"].(map[string]string)["anchor"] != "sha256:"+strings.Repeat("c", 64) || len(got["composed"].(map[string]string)) != 1 { + t.Errorf("compare = %+v", got) } // Read by watch (issue 1953 L5f): the same answer, each watched state started once, and no get per key of the // large states (the modules, their manifests, the composed record). @@ -405,14 +400,14 @@ func wantsVerbs(t *testing.T) { if werr != nil { t.Fatal(werr) } - if ws := wout.(map[string]any)["splits"].([]assign.Split); len(ws) != 1 || ws[0].Module != "web" { - t.Errorf("splits by watch = %+v", ws) + if got := wout.(map[string]any); got["composed"].(map[string]string)["anchor"] != "sha256:"+strings.Repeat("c", 64) { + t.Errorf("compare by watch = %+v", got) } } if n := watches[manifestsState+" by key"]; n == 0 || n > len(st[manifestsState].values) { t.Errorf("the manifests were read by key %d times, want each once", n) } - for _, state := range []string{modulesState, composedState, health.FindingsState} { + for _, state := range []string{modulesState, haveState, health.FindingsState} { if watches[state] != 1 { t.Errorf("%s was watched %d times, want once", state, watches[state]) } @@ -432,9 +427,6 @@ func wantsVerbs(t *testing.T) { Put: func(k string, v []byte) error { findings[k] = v; return nil }, Delete: func(k string) error { delete(findings, k); return nil }, Keys: func() ([]string, error) { return []string{"module.gone.policy-split"}, nil }}} - for k, v := range st[composedState].values { - p.w.putEntry(delivery.ControllerComposedBucket, k, v, 1, time.Now()) - } man := map[string]catalogue.Manifest{} for _, name := range []string{"web", "photos"} { raw, _, _, _ := st.get(modulesState, name) diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/wants_tools.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/wants_tools.go index 68b64ad..2a45f88 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/wants_tools.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/wants_tools.go @@ -19,15 +19,14 @@ import ( // The seat mesh-wants' verbs (novox/hq ADR 0565 §7, §8, §9, §15; issue 1953 D4-D6), served through the tool runner beside the // put tools and mesh-placement's verbs. `upgrade` reads and sets a person's upgrade policy, kept in the state `policies` -// (each set recorded as a hand act and said as policy-changed), and with compare lists every module whose policy differs from -// the one the controller writes beside its compositions; `bus` says what a bus upgrade would do. The assigner's process reads +// (each set recorded as a hand act and said as policy-changed), and with compare lists the digest of the composition each node's +// own have names (the controller writes no policy any more, so no module's policy differs); `bus` says what a bus upgrade would do. The assigner's process reads // `policies` when it judges a move and writes the finding policy-split while a split stands. // The states the verbs read, as the runtime names them. const ( policiesState = delivery.AssignerPoliciesState manifestsState = delivery.IndexerModule + ".manifests" - composedState = "mesh-controller.composed" // PolicyChangedEvent is the seat's event of a person's policy set or taken back. PolicyChangedEvent = "policy-changed" // busStepCause is the cause the bus's step is recorded under in the hand-act log. @@ -146,15 +145,23 @@ func (s *wantsTools) doUpgrade(args map[string]any, by string) (any, error) { } chosen, unreadable := assign.DecodePolicies(raw) if arg(args, "compare") == "true" { - composed, err := s.values(composedState) + haves, err := s.values(haveState) if err != nil { return nil, err } - splits := assign.Splits(manifests, chosen, assign.ControllerPolicies(composed)) + composed := map[string]string{} + for key, raw := range haves { + if node, _, isNode, err := delivery.ParseHaveKey(key); err == nil && isNode { + if h, err := delivery.DecodeHaveNode(raw); err == nil && h.Composed != "" { + composed[node] = h.Composed + } + } + } + splits := assign.Splits(manifests, chosen, nil) // the controller writes no policy to differ from (ADR 0571 §6) if splits == nil { splits = []assign.Split{} } - out := map[string]any{"splits": splits, "empty": len(splits) == 0} + out := map[string]any{"splits": splits, "empty": len(splits) == 0, "composed": composed} // The assigner's findings, its said conditions and its policy splits as the condition keeper reads them (§8, §15). if found, err := s.values(health.FindingsState); err != nil { out["findings-unread"] = err.Error() diff --git a/modules/mesh-delivery-assigner/internal/assign/policy.go b/modules/mesh-delivery-assigner/internal/assign/policy.go index e877ba7..9d3b5e5 100644 --- a/modules/mesh-delivery-assigner/internal/assign/policy.go +++ b/modules/mesh-delivery-assigner/internal/assign/policy.go @@ -48,26 +48,6 @@ func PolicyOf(m catalogue.Manifest, chosen map[string]catalogue.PersonPolicy) (p return catalogue.Upgrade(m, c) } -// ControllerPolicies is, by module, every policy the controller writes beside a composition's digest of it. -func ControllerPolicies(composed map[string][]byte) map[string][]string { - out := map[string][]string{} - for key, raw := range composed { - _, module, _, isNode, err := delivery.ParseComposedKey(key) - if err != nil || isNode { - continue - } - d, err := delivery.DecodeComposedDigest(raw) - if err != nil || d.Policy == "" { - continue - } - if !contains(out[module], d.Policy) { - out[module] = append(out[module], d.Policy) - sort.Strings(out[module]) - } - } - return out -} - func contains(list []string, s string) bool { for _, v := range list { if v == s { diff --git a/modules/mesh-delivery-assigner/internal/assign/wants.go b/modules/mesh-delivery-assigner/internal/assign/wants.go index e7f7d42..fe6ade5 100644 --- a/modules/mesh-delivery-assigner/internal/assign/wants.go +++ b/modules/mesh-delivery-assigner/internal/assign/wants.go @@ -39,8 +39,8 @@ type Module struct { // Chosen is a person's choice of the module's upgrade policy (the assigner's `policies`, ADR 0565 §7); nil: none. Chosen *catalogue.PersonPolicy Nodes []string - // Composed answers the controller's composition of the module for a node at a fingerprint (mesh-controller_composed): its - // digest and the judgement of the move to it, and whether it exists. Nil: none exists (ADR 0539 §1, §6). + // Composed answers the composition of the module for a node at a fingerprint: the digest the node's own have names (a + // placed node composes its own, ADR 0571 §6), and whether it names one. Nil: none exists (ADR 0539 §1, §6). Composed func(node, fp string) (delivery.ComposedDigest, bool) // Allowed says whether the operator answered yes to the record ask about the move of this module on node to the composition // with this digest (ADR 0539 §14). Nil: none did. @@ -131,7 +131,7 @@ func holds(m Module, node string, n Nodes, ordering bool) (bool, int, string) { short(m.FP)) } if _, ok := m.composition(node, m.FP); !ok { - return false, delivery.RuleComposed, fmt.Sprintf("the controller has not composed %s for %s at %s", m.Name, node, short(m.FP)) + return false, delivery.RuleComposed, fmt.Sprintf("%s has named no composition of its own for %s at %s yet", node, m.Name, short(m.FP)) } if words, waiting := m.provisionWaiting(node); waiting { return false, delivery.RuleProvisions, words @@ -534,7 +534,7 @@ func (m Module) selfDerived(node string, before delivery.Want, had bool, next de d, there := m.composition(node, next.FP) if !there || d.Digest == "" { out.Rules[node] = Holding{Rule: delivery.RuleComposed, Words: fmt.Sprintf("%s on %s was composed by the node while it was placed, "+ - "and the controller has not composed it at %s, so its want stays", m.Name, node, short(next.FP))} + "and no composition of its own is named at %s now, so its want stays", m.Name, node, short(next.FP))} return next, false } at := m diff --git a/modules/mesh-delivery-assigner/manifest_test.go b/modules/mesh-delivery-assigner/manifest_test.go index 7f208a0..9d6bb18 100644 --- a/modules/mesh-delivery-assigner/manifest_test.go +++ b/modules/mesh-delivery-assigner/manifest_test.go @@ -33,7 +33,7 @@ func TestManifest(t *testing.T) { } reads := slices.Clone(m.Reads) slices.Sort(reads) - want := []string{"mesh-build-go.steps", "mesh-conditions.takeover", "mesh-config.kept", "mesh-config.resolved", "mesh-controller.composed", + want := []string{"mesh-build-go.steps", "mesh-conditions.takeover", "mesh-config.kept", "mesh-config.resolved", "mesh-delivery-builder.build-log", "mesh-delivery-builder.builds", "mesh-delivery-indexer.candidates", "mesh-delivery-indexer.manifests", "mesh-delivery-indexer.modules", "mesh-delivery-teller.answers", "mesh-delivery-watchman.presence", "mesh-grants.grants", "mesh-provisioner.provisions", "node-engine.have"} if !reflect.DeepEqual(reads, want) { diff --git a/modules/mesh-delivery-assigner/module.json b/modules/mesh-delivery-assigner/module.json index 7cc4da2..037ecd5 100644 --- a/modules/mesh-delivery-assigner/module.json +++ b/modules/mesh-delivery-assigner/module.json @@ -30,7 +30,6 @@ "mesh-conditions.takeover", "mesh-config.kept", "mesh-config.resolved", - "mesh-controller.composed", "mesh-delivery-builder.build-log", "mesh-delivery-builder.builds", "mesh-delivery-indexer.candidates",