Join item 3: the condition keeper reads every finding the registry milestone added
The builder's four kinds, the indexer's four, the package seats' token refused and the owners' view too large get their homes; the keeper reads the findings of every reader of the indexer's and the assigner's state (teller, enrolment, builder, checker, view), and asks the indexer's findings of its read tool and follows its views events, as the assigner's (ADR 0615 §1). Rows in TestEveryControllerKindHasItsHome and the manifest test; each failed before the change. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -102,6 +102,23 @@ var Homes = map[string]Home{
|
||||
// A reader whose owner does not answer its first view past two minutes (ADR 0615 §6): written by each reader in its own
|
||||
// findings (mesh-config, mesh-vault), so the kind has no one observer.
|
||||
"first-view-unanswered": {Source: "views", Why: "every reader of the indexer's or the assigner's state writes its own"},
|
||||
// An owner's views event too large to say (ADR 0615 §5): written by each owner of a views family in its own findings
|
||||
// (the indexer, the assigner), so the kind has no one observer.
|
||||
"view-too-large": {Source: "views", Why: "every owner of a views family writes its own"},
|
||||
// The builder's own (design 51): a build that ended failed, a floor whose holder said nothing past its bound, an old
|
||||
// form held seven days by a counted node-engine, a tag's removal asked and not done.
|
||||
"build-failed": {Source: "builder", Observer: builder},
|
||||
"floor-silent": {Source: "builder", Observer: builder},
|
||||
"old-form-held": {Source: "builder", Observer: builder},
|
||||
"tag-removal-not-done": {Source: "builder", Observer: builder},
|
||||
// The indexer's own (design 26, ADR 0625): a seat definition that does not parse, generated types out of step with
|
||||
// their definition, one seat defined by two repositories' trunks, a manifest accepted and not said.
|
||||
"seat-definition-unparsed": {Source: "indexer", Observer: indexer},
|
||||
"generated-types-out-of-step": {Source: "indexer", Observer: indexer},
|
||||
"seat-defined-twice": {Source: "indexer", Observer: indexer},
|
||||
"accepted-unsaid": {Source: "indexer", Observer: indexer},
|
||||
// The package seats' holder (design 32): the forge refused the packages account's write token.
|
||||
"packages-token-refused": {Source: "gitea", Observer: gitea},
|
||||
// The kinds that end with the controller and are carried until its lease write (clauses 4, 9).
|
||||
"controller-deaf": {Source: "S4", Controller: true, Carried: true},
|
||||
"lease-lost": {Source: "S12", Controller: true, Carried: true},
|
||||
@@ -166,6 +183,10 @@ const (
|
||||
artifactStore = "artifact-store-tools"
|
||||
configModule = "mesh-config"
|
||||
vaultModule = "mesh-vault"
|
||||
builder = "mesh-delivery-builder"
|
||||
indexer = "mesh-delivery-indexer"
|
||||
gitea = "gitea"
|
||||
enrolment = "mesh-enrolment"
|
||||
)
|
||||
|
||||
// homeOf is the home of a condition's kind, and whether the table has one.
|
||||
|
||||
@@ -43,7 +43,10 @@ var Observers = []string{health.WatchmanModule, health.SelfCheckModule, health.H
|
||||
"mesh-provisioner", "messenger", artifactStore, configModule, vaultModule,
|
||||
// The readers of the indexer's and the assigner's state say a first view unanswered past its bound in their own findings
|
||||
// (ADR 0615 §6).
|
||||
"mesh-watcher", "minio", "nfs-server", "gitea", "mesh-build-go"}
|
||||
"mesh-watcher", "minio", "nfs-server", gitea, "mesh-build-go",
|
||||
// The builder's, the indexer's (asked of its read tool and followed by its views events, ADR 0615 §1) and the other
|
||||
// readers' of the indexer's and the assigner's state (the registry milestone's join).
|
||||
builder, indexer, "mesh-delivery-checker", "mesh-delivery-teller", "mesh-delivery-view", enrolment}
|
||||
|
||||
// The other states it reads, as `<module>.<name>`.
|
||||
const (
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -276,10 +277,16 @@ func TestEveryControllerKindHasItsHome(t *testing.T) {
|
||||
}
|
||||
for kind, observer := range map[string]string{"needs-operator": watchman, "machine-network": watchman, "lease-split": selfCheck,
|
||||
"data-shrank": selfCheck, "retire-waiting": provisioner, "asks-undelivered": messenger,
|
||||
"image-missing": artifactStore} {
|
||||
"image-missing": artifactStore, "build-failed": builder, "floor-silent": builder, "old-form-held": builder,
|
||||
"tag-removal-not-done": builder, "seat-definition-unparsed": indexer, "generated-types-out-of-step": indexer,
|
||||
"seat-defined-twice": indexer, "accepted-unsaid": indexer, "packages-token-refused": gitea} {
|
||||
if h, ok := Homes[kind]; !ok || h.Observer != observer || h.Carried {
|
||||
t.Errorf("%s's home is %+v", kind, h)
|
||||
}
|
||||
// The keeper reads every observer's findings that a kind's home names (the registry milestone's join).
|
||||
if !slices.Contains(Observers, observer) {
|
||||
t.Errorf("%s's observer %s is not read by the keeper", kind, observer)
|
||||
}
|
||||
}
|
||||
for _, kind := range []string{"resolver-wrong", "holder-silent", "archives-missing", "archives-unheld", "binding-kept",
|
||||
"binding-moved", "binding-moving", "grant-composes-nothing", "root-not-free", "cleanup-waiting", "data-held-twice"} {
|
||||
@@ -294,7 +301,22 @@ func TestEveryControllerKindHasItsHome(t *testing.T) {
|
||||
t.Errorf("the ended probe's kind %s is %+v", kind, h)
|
||||
}
|
||||
}
|
||||
if len(Homes) != 89 || carried != 37 { // 19 of ADR 0564, the 63 of the table, plan-failed and stalled, mesh-config's four (design 32) and the readers' unanswered first view
|
||||
// The readers' unanswered first view and the owners' views too large to say are every reader's and owner's own.
|
||||
for _, kind := range []string{"first-view-unanswered", "view-too-large"} {
|
||||
if h := Homes[kind]; h.Observer != "" || h.Carried || h.Controller {
|
||||
t.Errorf("%s's home is %+v", kind, h)
|
||||
}
|
||||
}
|
||||
// Each module that writes a reader's unanswered first view (ADR 0615 §6) is read.
|
||||
for _, reader := range []string{watchman, "mesh-delivery-teller", enrolment, builder, "mesh-delivery-checker",
|
||||
"mesh-delivery-view", indexer, configModule, vaultModule, gitea} {
|
||||
if !slices.Contains(Observers, reader) {
|
||||
t.Errorf("the reader %s's findings are not read by the keeper", reader)
|
||||
}
|
||||
}
|
||||
// 19 of ADR 0564, the 63 of the table, plan-failed and stalled, mesh-config's four (design 32), the readers' unanswered
|
||||
// first view, the owners' view too large, the builder's four, the indexer's four and the package seats' token refused.
|
||||
if len(Homes) != 99 || carried != 37 {
|
||||
t.Errorf("the table holds %d kinds, %d carried", len(Homes), carried)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func watch(k *Keeper, v *views.Reader, state, observer string, handle func(stdio
|
||||
for wait := 5 * time.Second; ; wait = min(wait*2, 5*time.Minute) {
|
||||
var err error
|
||||
if v.Follows(state) {
|
||||
// The assigner's states are asked once of its read tool and followed by its events (ADR 0615).
|
||||
// The assigner's and the indexer's states are asked once of their read tools and followed by their events (ADR 0615).
|
||||
err = v.Watch(state, func(key string, value []byte, gone bool) {
|
||||
op := stdio.OpPut
|
||||
if gone {
|
||||
@@ -143,15 +143,18 @@ const (
|
||||
WantsTool = delivery.AssignerModule + ".assigner_read_wants"
|
||||
PlacementTool = delivery.AssignerModule + ".assigner_read_placement"
|
||||
FindingsTool = delivery.AssignerModule + ".assigner_read_findings"
|
||||
// IndexerFindingsTool is the indexer's read tool of its findings: the indexer's state, too, is asked of its owner.
|
||||
IndexerFindingsTool = delivery.IndexerModule + ".indexer_read_findings"
|
||||
)
|
||||
|
||||
// NewViews is the keeper's pictures of the assigner's wants, placement and findings. A first view it cannot get past its
|
||||
// NewViews is the keeper's pictures of the assigner's wants, placement and findings and of the indexer's findings. A first view it cannot get past its
|
||||
// bound is a finding of its own, taken in as any observer's: the keeper raises the condition itself.
|
||||
func NewViews(k *Keeper) *views.Reader {
|
||||
v := &views.Reader{Module: Module, Logf: logf, Findings: ownFindings{k}, Acts: handacts.Recorder{Ask: stdio.Ask}}
|
||||
v.Follow(delivery.AssignerModule, "wants", WantsTool)
|
||||
v.Follow(delivery.AssignerModule, "placement", PlacementTool)
|
||||
v.Follow(delivery.AssignerModule, health.FindingsState, FindingsTool)
|
||||
v.Follow(delivery.IndexerModule, health.FindingsState, IndexerFindingsTool)
|
||||
return v
|
||||
}
|
||||
|
||||
|
||||
@@ -30,16 +30,17 @@ func TestTheManifestSaysWhatTheCodeDoes(t *testing.T) {
|
||||
!slices.Equal(Verbs, catalogue.VerbNames(seat.Serves)) {
|
||||
t.Errorf("module %s runs as %s and claims %+v; the seat serves %v", m.Module, m.RunsAs, m.Claims, catalogue.VerbNames(seat.Serves))
|
||||
}
|
||||
// The assigner's wants, placement and findings are asked once of its read tools and followed by its events, not read
|
||||
// (ADR 0615 §1).
|
||||
// The assigner's wants, placement and findings, and the indexer's findings, are asked once of their read tools and
|
||||
// followed by their events, not read (ADR 0615 §1).
|
||||
reads := []string{HavesRead, AttemptsRead}
|
||||
for _, o := range Observers {
|
||||
if o != delivery.AssignerModule {
|
||||
if o != delivery.AssignerModule && o != delivery.IndexerModule {
|
||||
reads = append(reads, o+"."+health.FindingsState)
|
||||
}
|
||||
}
|
||||
if !slices.Equal(m.Invokes, []string{WantsTool, PlacementTool, FindingsTool, "seat:mesh-hand-acts.hand-act"}) ||
|
||||
!slices.Equal(m.Consumes, []string{"mesh-delivery-assigner.views.wants", "mesh-delivery-assigner.views.placement", "mesh-delivery-assigner.views.findings"}) {
|
||||
if !slices.Equal(m.Invokes, []string{WantsTool, PlacementTool, FindingsTool, IndexerFindingsTool, "seat:mesh-hand-acts.hand-act"}) ||
|
||||
!slices.Equal(m.Consumes, []string{"mesh-delivery-assigner.views.wants", "mesh-delivery-assigner.views.placement",
|
||||
"mesh-delivery-assigner.views.findings", "mesh-delivery-indexer.views.findings"}) {
|
||||
t.Errorf("invokes %v, consumes %v", m.Invokes, m.Consumes)
|
||||
}
|
||||
slices.Sort(reads)
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
"nfs-server.findings",
|
||||
"gitea.findings",
|
||||
"mesh-build-go.findings",
|
||||
"mesh-delivery-builder.findings",
|
||||
"mesh-delivery-checker.findings",
|
||||
"mesh-delivery-teller.findings",
|
||||
"mesh-delivery-view.findings",
|
||||
"mesh-enrolment.findings",
|
||||
"mesh-healers.attempts",
|
||||
"node-engine.have"
|
||||
],
|
||||
@@ -34,12 +39,14 @@
|
||||
"mesh-delivery-assigner.assigner_read_wants",
|
||||
"mesh-delivery-assigner.assigner_read_placement",
|
||||
"mesh-delivery-assigner.assigner_read_findings",
|
||||
"mesh-delivery-indexer.indexer_read_findings",
|
||||
"seat:mesh-hand-acts.hand-act"
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-delivery-assigner.views.wants",
|
||||
"mesh-delivery-assigner.views.placement",
|
||||
"mesh-delivery-assigner.views.findings"
|
||||
"mesh-delivery-assigner.views.findings",
|
||||
"mesh-delivery-indexer.views.findings"
|
||||
],
|
||||
"state": [
|
||||
"conditions",
|
||||
|
||||
Reference in New Issue
Block a user