diff --git a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/consumes.go b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/consumes.go index d176cf4f..e1aa03d0 100644 --- a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/consumes.go +++ b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/consumes.go @@ -46,6 +46,13 @@ func consumed(w *watch.Watchman, subject string, body []byte, logf func(string, return } w.Accepted(a) + case subject == meshcatalog.SubjectManifestRefused: + var r meshcatalog.ManifestRefusedEvent + if err := json.Unmarshal(body, &r); err != nil || r.Module == "" { + logf("a manifest-refused that does not read is left: %v", err) + return + } + w.ManifestRefused(r) case pipelineSubject(w, subject, body): case engineWaitSubject(w, subject, body): case moduleWaitSubject(w, subject, body): diff --git a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/integration_test.go b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/integration_test.go index faad1c03..b5facb10 100644 --- a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/integration_test.go +++ b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/integration_test.go @@ -63,12 +63,12 @@ accounts { } ` -// serveOwners serves the assigner's wants and the indexer's modules as their owners do, by their read tools and views +// serveOwners serves the assigner's wants as its owner does, by their read tools and views // families (DLV-M5, ADR 0615): the watchman (n1) follows both, never their buckets. func serveOwners(t *testing.T, ctx context.Context, js jetstream.JetStream, nc *nats.Conn) { t.Helper() viewstest.Serve(t, ctx, js, nc, watch.AssignerModule, wantsState, watch.AssignerModule+".assigner_read_wants", "n1_"+watch.WatchmanModule) - viewstest.Serve(t, ctx, js, nc, watch.IndexerModule, modulesState, watch.IndexerModule+".indexer_read_modules", "n1_"+watch.WatchmanModule) + } // makeEvents makes EVENTS and the watchman's durable consumer of the build seats' events, as the controller and the grants part diff --git a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main.go b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main.go index 93b5454c..f2ffe4be 100644 --- a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main.go +++ b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main.go @@ -194,8 +194,7 @@ func createdOr(e jetstream.KeyValueEntry, at time.Time) time.Time { var firstViewsBucket = watch.WatchmanModule + "_" + views.StatusState const ( - wantsState = "wants" - modulesState = "modules" + wantsState = "wants" // The owners' views families, as their manifests' `streams` name them. ) @@ -261,16 +260,11 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro if err != nil { return err } - modules, err := reader.Follow(watch.IndexerModule, modulesState, watch.IndexerModule+".indexer_read_modules") - if err != nil { - return err - } w := watch.New(&kvOut{ctx: ctx, presence: kvs.presence, pulse: kvs.pulse, stuk: kvs.stuck, findings: held, js: js, cred: cred}, time.Now) w.Logf(logger.Printf) // What the wants and the modules hold is ended by their own late read (watch.ReadLate), never by the start's end. w.Awaits(watch.AssignerWantsBucket) - w.Awaits(watch.ModulesBucket) // A test shortens how long a move may take; the mesh never sets it. if v := strings.TrimSpace(getenv("MESH_DELIVERY_PULSE_BOUND")); v != "" { d, err := time.ParseDuration(v) @@ -416,6 +410,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro logger.Printf("take-in: no connection to ask %s (%v), so a wait the indexer held before this start is said only once a take-in event of it is heard", pendingTool, err) } else { seedTakeIn(w, calls.Call, logger.Printf) + seedVerdicts(w, calls.Call, logger.Printf) calls.Close() } // The take-in events are the indexer's ordinary events (its emits), heard on the shared events stream through this @@ -452,9 +447,6 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // Every part has registered: the hub pulls the module's durable, and the watchman's other consumers open. hearConsumed(ctx, js, cred, hub, w, logger.Printf) defer hub.Stop() - // The indexer's modules (ADR 0578 §1): a module whose value carries a refusal of its manifest is a finding. - verdictEach := func(e jetstream.KeyValueEntry) { w.ModuleVerdict(e.Key(), e.Value(), opOf(e)) } - go func() { errs <- readLate(ctx, w, modules, watch.ModulesBucket, verdictEach) }() if haveSeen != nil { go func() { errs <- follow(ctx, haveSeen, func(e jetstream.KeyValueEntry) { w.Have(e.Key(), e.Value(), opOf(e)) }) @@ -522,6 +514,20 @@ func seedTakeIn(w *watch.Watchman, call func(key string, body any) (json.RawMess logf("take-in: %s cannot be asked (%v), so a wait the indexer held before this start is said only once a take-in event of it is heard", pendingTool, err) } +// seedVerdicts asks the indexer's verdicts and raises the findings they hold (design 47 G §500): a verdict said while the watchman was +// down is then not lost. An indexer that does not answer is said: the findings are then raised from the verdicts heard after. +func seedVerdicts(w *watch.Watchman, call func(key string, body any) (json.RawMessage, error), logf func(string, ...any)) { + raw, err := call(watch.VerdictsTool, map[string]any{"all": true}) + if err == nil { + var rows []watch.VerdictRow + if rows, err = watch.DecodeVerdictRows(raw); err == nil { + w.SeedVerdicts(rows) + return + } + } + logf("verdicts: %s cannot be asked (%v), so a manifest refused before this start is said only once a verdict of it is heard", watch.VerdictsTool, err) +} + // takeInHeard hands one take-in event of the indexer to the watchman, by its name relative to the indexer, and acknowledges it; // one that is not a take-in event is said and acknowledged, since hearing it again would not read it. func takeInHeard(w *watch.Watchman, m jetstream.Msg, logf func(string, ...any)) { diff --git a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main_test.go b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main_test.go index 1c662686..7d24b481 100644 --- a/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main_test.go +++ b/modules/mesh-delivery-watchman/cmd/mesh-delivery-watchman/main_test.go @@ -75,6 +75,14 @@ func TestRunNeedsItsCredential(t *testing.T) { // 1135/AC6 t.Fatalf("created left %v", out.findings) } }) + t.Run("design 47 G §500: the indexer's manifest-refused reaches the watchman by its subject", func(t *testing.T) { + out := &findingsOut{findings: map[string]bool{}} + w := watch.New(out, time.Now) + consumed(w, "mesh.seat.mesh-catalog.event.manifest-refused", []byte(`{"module":"m","digest":"d","problems":["x"]}`), func(string, ...any) {}) + if !out.findings[watch.FindingKey(watch.ScopeModule, "m", watch.KindManifestRefused)] { + t.Fatalf("a refused manifest reached %v", out.findings) + } + }) t.Run("design 47 G §499, §541: a node-engine's wait-held and wait-ended reach the watchman by their subjects", func(t *testing.T) { out := &findingsOut{findings: map[string]bool{}} w := watch.New(out, time.Now) diff --git a/modules/mesh-delivery-watchman/internal/watch/busstate.go b/modules/mesh-delivery-watchman/internal/watch/busstate.go index 11d2d770..2def5880 100644 --- a/modules/mesh-delivery-watchman/internal/watch/busstate.go +++ b/modules/mesh-delivery-watchman/internal/watch/busstate.go @@ -64,6 +64,7 @@ func refusedKey(module, local string) string { func (w *Watchman) Accepted(a meshcatalog.ManifestAcceptedEvent) { w.mu.Lock() defer w.mu.Unlock() + w.manifestAccepted(a.Module, a.Problems) // §500: the problems a stricter validator finds are the module's warning asked := map[string]bool{} for _, e := range a.BusState { if e.Name == "" { diff --git a/modules/mesh-delivery-watchman/internal/watch/findings_test.go b/modules/mesh-delivery-watchman/internal/watch/findings_test.go index 6214cee1..0c6f3d11 100644 --- a/modules/mesh-delivery-watchman/internal/watch/findings_test.go +++ b/modules/mesh-delivery-watchman/internal/watch/findings_test.go @@ -187,43 +187,32 @@ func TestTheWatchmansFindings(t *testing.T) { next := "m.00000000000000000043" w.TakeIn(takeInEvent(t, takein.TakeInPending, next), takeInBody(t, takein.TakeInPending, next, t0)) }, map[string]string{FindingKey(ScopeDelivery, "m.00000000000000000043", KindTakeInWaits): Warning}}, - {"ADR 0578 §1: a module whose value carries a refusal of its manifest is a finding until it is accepted", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) { - value := func(verdict string, problems ...string) []byte { - b, err := meshcatalogclient.EncodeModule(meshcatalog.ModulesByModuleValue{Fp2: "src2:" + strings.Repeat("a", 64), Manifest: strings.Repeat("b", 64), - Repository: "novox/mesh-catalog", Commit: "c", Verdict: verdict, Problems: problems}) - if err != nil { - t.Fatal(err) - } - return b - } - w.ModuleVerdict("nats", value(meshcatalogclient.VerdictRefused, "removes a stream"), Put) - w.ModuleVerdict("power", value(meshcatalogclient.VerdictRefused, "shows nothing"), Put) + {"design 47 G §500: manifest-refused raises the refusal, manifest-accepted clears it and carries an outgrown manifest's problems", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) { + w.ManifestRefused(meshcatalog.ManifestRefusedEvent{Module: "nats", Problems: []string{"removes a stream"}}) + w.ManifestRefused(meshcatalog.ManifestRefusedEvent{Module: "power", Problems: []string{"shows nothing"}}) k := FindingKey(ScopeModule, "nats", KindManifestRefused) if f := o.findings[k]; !strings.Contains(f.Summary, "refused the manifest of nats: removes a stream") { t.Fatalf("findings = %v", o.findings) } - w.ModuleVerdict("nats", value(""), Put) - w.ModuleVerdict("power", nil, Delete) + w.Accepted(meshcatalog.ManifestAcceptedEvent{Module: "nats", Digest: strings.Repeat("d", 64)}) + w.Accepted(meshcatalog.ManifestAcceptedEvent{Module: "power", Digest: strings.Repeat("d", 64)}) // ADR 0579 §1: an accepted manifest a stricter judge outgrew is a warning until mended. - outgrown, _ := meshcatalogclient.EncodeModule(meshcatalog.ModulesByModuleValue{Fp2: "src2:" + strings.Repeat("a", 64), Manifest: strings.Repeat("b", 64), - Repository: "novox/mesh-tools", Commit: "c", Warnings: []string{"says no credential form"}}) - w.ModuleVerdict("node-tools", outgrown, Put) + w.Accepted(meshcatalog.ManifestAcceptedEvent{Module: "node-tools", Digest: strings.Repeat("d", 64), Problems: []string{"says no credential form"}}) if f := o.findings[FindingKey(ScopeModule, "node-tools", KindManifestOutgrown)]; f.Severity != Warning || !strings.Contains(f.Summary, "says no credential form") { t.Fatalf("findings = %v", o.findings) } - w.ModuleVerdict("node-tools", value(""), Put) - // Clause 3 of the record on a release's Approve: a manifest that waits for a judge that knows its fields is its own - // warning (a refusal in the value, naming the fields), not manifest-refused, and goes when it is accepted. - waiting, _ := meshcatalogclient.EncodeModule(meshcatalog.ModulesByModuleValue{Fp2: "src2:" + strings.Repeat("a", 64), Manifest: strings.Repeat("b", 64), - Repository: "novox/mesh-catalog", Commit: "c", Verdict: meshcatalogclient.VerdictRefused, Problems: []string{"waits"}, Unknown: []string{"core-credentials"}}) - w.ModuleVerdict("nats", waiting, Put) - if f := o.findings[FindingKey(ScopeModule, "nats", KindManifestWaits)]; f.Severity != Warning || !strings.Contains(f.Summary, "core-credentials") { + w.Accepted(meshcatalog.ManifestAcceptedEvent{Module: "node-tools", Digest: strings.Repeat("e", 64), Problems: []string{}}) + // The start seeds from the indexer's verdicts: the newest of each module counts. + w.SeedVerdicts([]VerdictRow{ + {Module: "nats", State: meshcatalogclient.VerdictRefused, Problems: []string{"old"}, At: t0}, + {Module: "nats", State: meshcatalogclient.VerdictAccepted, At: t0.Add(time.Hour)}, + {Module: "power", State: meshcatalogclient.VerdictRefused, Problems: []string{"shows nothing"}, At: t0}, + {Module: "node-tools", State: meshcatalogclient.VerdictAccepted, Warnings: []string{"w"}, At: t0}}) + if len(o.findings) != 2 || o.findings[FindingKey(ScopeModule, "power", KindManifestRefused)].Kind == "" || o.findings[FindingKey(ScopeModule, "node-tools", KindManifestOutgrown)].Kind == "" { t.Fatalf("findings = %v", o.findings) } - if _, refused := o.findings[FindingKey(ScopeModule, "nats", KindManifestRefused)]; refused { - t.Fatalf("a waiting manifest was found refused: %v", o.findings) - } - w.ModuleVerdict("nats", value(""), Put) + w.Accepted(meshcatalog.ManifestAcceptedEvent{Module: "power"}) + w.Accepted(meshcatalog.ManifestAcceptedEvent{Module: "node-tools"}) }, map[string]string{}}, {"DLV-W1, 1966/AC37-AC38 (ADR 0595 §4, design 25 § 12.2): an accepted entry the bus module says nothing of in five minutes is overdue until created; a refused one stands until created; a later verdict no longer asking ends both", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) { accepted := func(locals ...string) meshcatalog.ManifestAcceptedEvent { diff --git a/modules/mesh-delivery-watchman/internal/watch/names.go b/modules/mesh-delivery-watchman/internal/watch/names.go index 5759cc5b..d8e9121d 100644 --- a/modules/mesh-delivery-watchman/internal/watch/names.go +++ b/modules/mesh-delivery-watchman/internal/watch/names.go @@ -25,13 +25,10 @@ const ( NodeHealthBucket = "mesh-host_health" // AssignerWantsBucket is the assigner's state wants, followed by its views family (consumes: mesh-delivery-assigner.views.wants). AssignerWantsBucket = AssignerModule + "_wants" - // ModulesBucket is the indexer's state modules, followed by its views family (consumes: mesh-delivery-indexer.views.modules). - ModulesBucket = IndexerModule + "_modules" ) // The findings a value of another part is raised as, named by their words. const ( FindingManifestOutgrown = "manifest-outgrown" - FindingManifestWaits = "manifest-waits" FindingNodeAccountFallback = "node-account-fallback" ) diff --git a/modules/mesh-delivery-watchman/internal/watch/verdicts.go b/modules/mesh-delivery-watchman/internal/watch/verdicts.go index dcb2618c..dfdf8a58 100644 --- a/modules/mesh-delivery-watchman/internal/watch/verdicts.go +++ b/modules/mesh-delivery-watchman/internal/watch/verdicts.go @@ -1,9 +1,13 @@ package watch import ( + "encoding/json" + "fmt" "strings" + "time" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/clients/meshcatalogclient" + "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog" ) // KindManifestRefused is a module whose manifest the indexer's judge refused (novox/hq ADR 0578 §1): every reader holds @@ -14,66 +18,96 @@ const KindManifestRefused = "manifest-refused" // (novox/hq ADR 0579 §1): it stays accepted and runs; the warning stands until the manifest is mended. const KindManifestOutgrown = FindingManifestOutgrown -// KindManifestWaits is a module whose manifest carries a field the indexer's judge does not know yet (novox/hq ADR 0578 -// §1, amended): every reader holds it as a refused one and keeps what runs, and the warning stands until a judge knows the -// field or the manifest is mended. -const KindManifestWaits = FindingManifestWaits +// The manifest findings are the indexer's verdicts heard as events (design 47 G §500): `manifest-refused` raises the refusal, and +// `manifest-accepted`, which carries `problems` (what a stricter validator finds in a manifest it still accepts), raises +// `manifest-outgrown` or, with none, clears it and any refusal. The watchman seeds both from the indexer's verdicts at its start +// (VerdictsTool). `manifest-waits` is no longer written: every revision is judged by a validator built from its own heads (§16). -// ModuleVerdict is a change of the indexer's value of a module (ModulesBucket): a value carrying a refusal is a -// finding, one that does not (accepted, or not judged yet) or a deleted key ends it. -func (w *Watchman) ModuleVerdict(module string, value []byte, op Op) { +// VerdictsTool is the indexer's tool that lists its verdicts, which seeds the findings at the start. +const VerdictsTool = IndexerModule + ".indexer_verdicts" + +// VerdictRow is one verdict as the tool lists it (the fields the watchman reads). +type VerdictRow struct { + Module string `json:"module"` + State string `json:"state"` + Problems []string `json:"problems"` + Warnings []string `json:"warnings"` + At time.Time `json:"at"` +} + +// ManifestRefused hears the seat mesh-catalog's manifest-refused: the module's manifest is refused until a mended one is accepted. +func (w *Watchman) ManifestRefused(e meshcatalog.ManifestRefusedEvent) { + if e.Module == "" { + w.say("a manifest-refused names no module, left") + return + } w.mu.Lock() defer w.mu.Unlock() - key := FindingKey(ScopeModule, module, KindManifestRefused) - outgrown := FindingKey(ScopeModule, module, KindManifestOutgrown) - waits := FindingKey(ScopeModule, module, KindManifestWaits) - if op != Put { - w.unfind(key) - w.unfind(outgrown) - w.unfind(waits) - return - } - m, err := meshcatalogclient.DecodeModule(value) - if err != nil { - w.say("the indexer's value of %s cannot be read, so whether its manifest is refused is left as it was: %v", module, err) - return - } - v := meshcatalogclient.ModuleVerdict(module, m) - if v != nil && meshcatalogclient.VerdictWaits(*v) { - w.unfind(key) - w.unfind(outgrown) - w.find(Finding{Scope: ScopeModule, ID: module, Kind: KindManifestWaits, Severity: Warning, Source: ModulesBucket, - Summary: meshcatalogclient.VerdictWhy(*v), - Said: strings.Join(v.Unknown, "; "), - Headline: "The manifest of " + module + " waits for a judge that knows its fields", - Explanation: "The manifest carries " + strings.Join(v.Unknown, ", ") + ", which the indexer's judge does not know yet, so every " + - "reader holds " + module + " as a refused one and keeps what runs; an indexer that knows the fields judges it again " + - "at its start, and the newest build of the indexer refuses a field it does not know.", - Needs: "nothing while a newer indexer is on its way; else a pull request that mends the manifest of " + module}) - return - } - w.unfind(waits) - if refused, _ := meshcatalogclient.TakeVerdict(v); !refused { - w.unfind(key) - if v == nil || len(v.Warnings) == 0 { - w.unfind(outgrown) - return + w.verdict(e.Module, e.Problems, nil, true) +} + +// manifestAccepted hears the problems a manifest-accepted carries (Accepted calls it, w.mu held): none clears the module's findings, some are its warning. +func (w *Watchman) manifestAccepted(module string, problems []string) { + w.verdict(module, nil, problems, false) +} + +// SeedVerdicts raises, at the start, the findings of the newest verdict of each module the indexer's tool listed: a refused one, or an +// accepted one with warnings. A module whose newest verdict is accepted clears both. +func (w *Watchman) SeedVerdicts(rows []VerdictRow) { + newest := map[string]VerdictRow{} + for _, r := range rows { + if old, ok := newest[r.Module]; !ok || r.At.After(old.At) { + newest[r.Module] = r } - w.find(Finding{Scope: ScopeModule, ID: module, Kind: KindManifestOutgrown, Severity: Warning, Source: ModulesBucket, - Summary: "the manifest of " + module + " breaks rules the indexer's judge holds it to now: " + strings.Join(v.Warnings, "; "), - Said: strings.Join(v.Warnings, "; "), - Headline: "The manifest of " + module + " needs mending", - Explanation: "A stricter judge found problems in a manifest it accepted before; " + module + " stays accepted and " + - "runs, and its next change is refused until they are mended (novox/hq ADR 0579).", + } + w.mu.Lock() + defer w.mu.Unlock() + for module, r := range newest { + switch r.State { + case meshcatalogclient.VerdictRefused: + w.verdict(module, r.Problems, nil, true) + case meshcatalogclient.VerdictAccepted: + w.verdict(module, nil, r.Warnings, false) + } + } +} + +// DecodeVerdictRows reads the answer of the indexer's verdicts tool. +func DecodeVerdictRows(raw []byte) ([]VerdictRow, error) { + var a struct { + Verdicts []VerdictRow `json:"verdicts"` + } + if err := json.Unmarshal(raw, &a); err != nil { + return nil, fmt.Errorf("not an answer of the indexer's verdicts: %w", err) + } + return a.Verdicts, nil +} + +// verdict writes and clears a module's manifest findings, w.mu held: a refusal (problems, refused) or an outgrown manifest (warnings). +func (w *Watchman) verdict(module string, problems, warnings []string, refused bool) { + refusedKey := FindingKey(ScopeModule, module, KindManifestRefused) + outgrownKey := FindingKey(ScopeModule, module, KindManifestOutgrown) + if refused { + w.unfind(outgrownKey) + w.find(Finding{Scope: ScopeModule, ID: module, Kind: KindManifestRefused, Severity: Warning, Source: "indexer.verdicts", + Summary: "the indexer's judge refused the manifest of " + module + ": " + strings.Join(problems, "; "), + Said: strings.Join(problems, "; "), + Headline: "The manifest of " + module + " is refused", + Explanation: "The indexer's judge refused it, so every node, the grants part and the assigner hold " + module + ": " + + "nothing of it changes until a mended manifest is merged, and every other module goes on.", Needs: "a pull request that mends the manifest of " + module}) return } - w.unfind(outgrown) - w.find(Finding{Scope: ScopeModule, ID: module, Kind: KindManifestRefused, Severity: Warning, Source: ModulesBucket, - Summary: meshcatalogclient.VerdictWhy(*v), - Said: strings.Join(v.Problems, "; "), - Headline: "The manifest of " + module + " is refused", - Explanation: "The indexer's judge refused it, so every node, the grants part and the assigner hold " + module + ": " + - "nothing of it changes until a mended manifest is merged, and every other module goes on.", + w.unfind(refusedKey) + if len(warnings) == 0 { + w.unfind(outgrownKey) + return + } + w.find(Finding{Scope: ScopeModule, ID: module, Kind: KindManifestOutgrown, Severity: Warning, Source: "indexer.verdicts", + Summary: "the manifest of " + module + " breaks rules the indexer's judge holds it to now: " + strings.Join(warnings, "; "), + Said: strings.Join(warnings, "; "), + Headline: "The manifest of " + module + " needs mending", + Explanation: "A stricter judge found problems in a manifest it accepted before; " + module + " stays accepted and " + + "runs, and its next change is refused until they are mended (novox/hq ADR 0579).", Needs: "a pull request that mends the manifest of " + module}) } diff --git a/modules/mesh-delivery-watchman/manifest_test.go b/modules/mesh-delivery-watchman/manifest_test.go index 27f85ec6..5597b29e 100644 --- a/modules/mesh-delivery-watchman/manifest_test.go +++ b/modules/mesh-delivery-watchman/manifest_test.go @@ -126,11 +126,11 @@ func TestManifestStateAndReads(t *testing.T) { // 1135/AC6 } // The join: its first view asked again by hand is a hand act, recorded through the seat (views.StatusTools). The waits the // indexer holds at the watchman's start are asked of its tool (ADR 0633 §5), a verb edge as the view's. - if want := []string{"mesh-delivery-assigner.assigner_read_wants", "mesh-delivery-indexer.indexer_pending", "mesh-delivery-indexer.indexer_read_modules", "seat:mesh-hand-acts.hand-act", "seat:mesh-conditions.conditions"}; !reflect.DeepEqual(m.Invokes, want) { + if want := []string{"mesh-delivery-assigner.assigner_read_wants", "mesh-delivery-indexer.indexer_pending", "mesh-delivery-indexer.indexer_verdicts", "seat:mesh-hand-acts.hand-act", "seat:mesh-conditions.conditions"}; !reflect.DeepEqual(m.Invokes, want) { t.Errorf("invokes = %v, want %v", m.Invokes, want) } // DLV-M5 its first views, 1585/T20 the indexer's take-in events, and DLV-W1 (ADR 0595 §4): the accepted verdicts and the bus module's created and refused, durably. - if want := []string{"mesh-delivery-assigner.views.wants", "mesh-delivery-indexer.take-in.pending", "mesh-delivery-indexer.take-in.taken", "mesh-delivery-indexer.views.modules", "mesh-catalog.manifest-accepted", "mesh-delivery.source-moved", "mesh-delivery.filling", "mesh-delivery.full", "mesh-delivery.room", "mesh-delivery.record-opened", "mesh-delivery.record-ended", "mesh-catalog.filling", "mesh-catalog.full", "mesh-catalog.room", "mesh-wants.filling", "mesh-wants.full", "mesh-wants.room", "mesh-grants.filling", "mesh-grants.full", "mesh-grants.room", "node-build-go.ask-taken", "node-build-go.step-progress", "node-build-go.step-ended", "node-build-image.ask-taken", "node-build-image.step-progress", "node-build-image.step-ended", "node-build-node.ask-taken", "node-build-node.step-progress", "node-build-node.step-ended", "mesh-pipeline-runner.pipeline-started", "mesh-pipeline-runner.step-started", "mesh-pipeline-runner.step-ended", "mesh-pipeline-runner.wait-held", "mesh-pipeline-runner.wait-ended", "mesh-wants.wait-held", "mesh-wants.wait-ended", "mesh-grants.wait-held", "mesh-grants.wait-ended", "mesh-delivery-builder.wait-held", "mesh-delivery-builder.wait-ended", "node-engine.wait-held", "node-engine.wait-ended", "mesh-broker.created", "mesh-broker.refused", "mesh-conditions.findings-asked"}; !reflect.DeepEqual(m.Consumes, want) { + if want := []string{"mesh-delivery-assigner.views.wants", "mesh-delivery-indexer.take-in.pending", "mesh-delivery-indexer.take-in.taken", "mesh-catalog.manifest-accepted", "mesh-catalog.manifest-refused", "mesh-delivery.source-moved", "mesh-delivery.filling", "mesh-delivery.full", "mesh-delivery.room", "mesh-delivery.record-opened", "mesh-delivery.record-ended", "mesh-catalog.filling", "mesh-catalog.full", "mesh-catalog.room", "mesh-wants.filling", "mesh-wants.full", "mesh-wants.room", "mesh-grants.filling", "mesh-grants.full", "mesh-grants.room", "node-build-go.ask-taken", "node-build-go.step-progress", "node-build-go.step-ended", "node-build-image.ask-taken", "node-build-image.step-progress", "node-build-image.step-ended", "node-build-node.ask-taken", "node-build-node.step-progress", "node-build-node.step-ended", "mesh-pipeline-runner.pipeline-started", "mesh-pipeline-runner.step-started", "mesh-pipeline-runner.step-ended", "mesh-pipeline-runner.wait-held", "mesh-pipeline-runner.wait-ended", "mesh-wants.wait-held", "mesh-wants.wait-ended", "mesh-grants.wait-held", "mesh-grants.wait-ended", "mesh-delivery-builder.wait-held", "mesh-delivery-builder.wait-ended", "node-engine.wait-held", "node-engine.wait-ended", "mesh-broker.created", "mesh-broker.refused", "mesh-conditions.findings-asked"}; !reflect.DeepEqual(m.Consumes, want) { t.Errorf("consumes = %v, want %v", m.Consumes, want) } // 1952/WM1: the watchman holds the seat mesh-watchdogs at mesh scope, its first seat (novox/hq ADR 0564 §1, §4). @@ -176,7 +176,6 @@ func TestManifestStateAndReads(t *testing.T) { // 1135/AC6 "health": {watch.NodeHealthBucket, bucket(m.Reads, "mesh-host.health")}, "wants": {watch.AssignerWantsBucket, bucket(m.Consumes, "mesh-delivery-assigner.views.wants")}, "provisions": {watch.ProvisionsBucket, bucket(m.Reads, "mesh-provisioner.provisions")}, - "modules": {watch.ModulesBucket, bucket(m.Consumes, "mesh-delivery-indexer.views.modules")}, "assigner": {watch.AssignerModule + ".assigner_read_wants", entry(m.Invokes, "mesh-delivery-assigner.assigner_read_wants")}, "indexer": {watch.IndexerModule + ".indexer_pending", entry(m.Invokes, "mesh-delivery-indexer.indexer_pending")}, } { diff --git a/modules/mesh-delivery-watchman/module.json b/modules/mesh-delivery-watchman/module.json index d74809c9..eee55b48 100644 --- a/modules/mesh-delivery-watchman/module.json +++ b/modules/mesh-delivery-watchman/module.json @@ -23,7 +23,7 @@ "invokes": [ "mesh-delivery-assigner.assigner_read_wants", "mesh-delivery-indexer.indexer_pending", - "mesh-delivery-indexer.indexer_read_modules", + "mesh-delivery-indexer.indexer_verdicts", "seat:mesh-hand-acts.hand-act", "seat:mesh-conditions.conditions" ], @@ -31,8 +31,8 @@ "mesh-delivery-assigner.views.wants", "mesh-delivery-indexer.take-in.pending", "mesh-delivery-indexer.take-in.taken", - "mesh-delivery-indexer.views.modules", "mesh-catalog.manifest-accepted", + "mesh-catalog.manifest-refused", "mesh-delivery.source-moved", "mesh-delivery.filling", "mesh-delivery.full",