From fb31cc4e99d2b4f94bdd6cb1b70996e7792602c8 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 22:02:06 +0100 Subject: [PATCH] The console reads the assigner's state assignments and imports the contracts' new paths (issue 1966) Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i --- README.md | 2 +- node-tools/go.mod | 4 +- node-tools/internal/bus/state.go | 2 +- node-tools/internal/bus/state_test.go | 2 +- node-tools/internal/console/address.go | 40 +++++++++---------- node-tools/internal/console/address_test.go | 2 +- node-tools/internal/console/console_test.go | 2 +- .../internal/console/firstviews_test.go | 4 +- .../internal/console/manifest_waits_test.go | 2 +- node-tools/internal/console/mcp.go | 8 ++-- node-tools/internal/console/runtimes_test.go | 16 ++++---- node-tools/internal/firstview/firstview.go | 8 ++-- .../firstview/firstview_integration_test.go | 2 +- .../internal/firstview/firstview_test.go | 34 ++++++++-------- node-tools/internal/meshtest/meshtest.go | 24 +++++------ node-tools/module.json | 2 +- 16 files changed, 77 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 0c40988..b419c2e 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ of the words agents use for the mesh's (`logs` finds the journal). Best first: a words in a name or a replaced command, then words in a description; seats before modules on a tie. Discovery asks the bus (ADR 0197): every runtime answers the NATS services protocol's `$SRV.PING` and -`$SRV.INFO` with what it serves at that moment, and the console reads where the placement seat's records +`$SRV.INFO` with what it serves at that moment, and the console reads where the assigner seat's records place each module. The console waits at least 750 ms, and up to 5 s for every runtime that answered PING to send what it serves — a large runtime's answer crossing the bus to a broker on another machine can arrive well after the rest. A runtime that said it is there and did not say what it serves, or diff --git a/node-tools/go.mod b/node-tools/go.mod index 089f779..3048652 100644 --- a/node-tools/go.mod +++ b/node-tools/go.mod @@ -5,8 +5,8 @@ go 1.26.0 require ( git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/provisioning/go/seats/meshprovisioner v0.0.0-00010101000000-000000000000 - git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient v0.0.0-00010101000000-000000000000 - git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000 diff --git a/node-tools/internal/bus/state.go b/node-tools/internal/bus/state.go index 4e53368..c3cade3 100644 --- a/node-tools/internal/bus/state.go +++ b/node-tools/internal/bus/state.go @@ -545,7 +545,7 @@ var credentialEndings = []string{"password", "passwd", "secret", "token", "crede // credentialField is the first field anywhere in a JSON value whose name says it is a credential, or "". The one shape a // credential-shaped name may hold is a provider reference, an object of exactly `node` and `module`, both strings: a -// placement's binding of the provision "secret" to the vault (issue 1126) names who provides it, never its value. Any +// the assignment's binding of the provision "secret" to the vault (issue 1126) names who provides it, never its value. Any // other shape under such a name is refused. func credentialField(value json.RawMessage) string { var v any diff --git a/node-tools/internal/bus/state_test.go b/node-tools/internal/bus/state_test.go index 6ce8393..243d017 100644 --- a/node-tools/internal/bus/state_test.go +++ b/node-tools/internal/bus/state_test.go @@ -15,7 +15,7 @@ func TestACredentialNamedFieldIsFoundAnywhereInAValue(t *testing.T) { `{"clientSecret":"s"}`: "clientSecret", `{"maxTokens":4096,"name":"a","generation":3}`: "", `"just a string"`: "", - // Issue 1126: a placement binds the provision "secret" to the vault; only an exact provider reference passes. + // Issue 1126: an assignment binds the provision "secret" to the vault; only an exact provider reference passes. `{"bindings":{"secret":{"node":"anchor","module":"mesh-vault"}}}`: "", `{"secret":{"value":"s"}}`: "secret", `{"secret":{"node":"anchor","module":"mesh-vault","value":"s"}}`: "secret", diff --git a/node-tools/internal/console/address.go b/node-tools/internal/console/address.go index 2a2de9f..7b884dd 100644 --- a/node-tools/internal/console/address.go +++ b/node-tools/internal/console/address.go @@ -17,8 +17,8 @@ package console // session — so a tool that arrived a minute ago is found without the client reconnecting. import ( - assigner "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" - "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + assigner "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient" + "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" meshcatalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" "git.novox.be/novox/mesh-sdk/go/catalogue" @@ -55,7 +55,7 @@ const ( // searchCap is how many matches a search answers before it says how many more there were. const searchCap = 25 -const grammar = "Addresses: `.` for a seat held once for the mesh (e.g. `mesh-module-assigner.placement`); " + +const grammar = "Addresses: `.` for a seat held once for the mesh (e.g. `mesh-module-assigner.assignments`); " + "`/.` for a seat every machine holds (e.g. `ace/node-packet-filter.rules`); " + "`/.` for a module on one machine (e.g. `novox/postgres.postgres_list_databases`); " + "and `.` also for a module whose instances are interchangeable." @@ -96,7 +96,7 @@ func discovery() []map[string]any { "for when an address is said to be missing or on another machine."}, {"name": verbFirstViews, "inputSchema": obj(map[string]any{}), "description": "The tool runner's first views of the four states it reads of the indexer and the assigner (the " + - "assigner's placement and seat-holders, the indexer's manifests and modules): for each, the owner, the tool " + + "assigner's assignments and seat-holders, the indexer's manifests and modules): for each, the owner, the tool " + "asked, the revision held and when it was made, how many keys, when it was asked and answered, how often " + "it was asked and how often by hand, whether its condition is raised, and why it was last asked. Read-only."}, {"name": verbFirstAgain, "inputSchema": obj(map[string]any{ @@ -145,7 +145,7 @@ type index struct { NotAnswering []string Listing *Listing // the flat catalogue the call path resolves subjects with Discovery announce.Discovery - // Recorded is where placement places each module that declares tools. + // Recorded is where the assigner places each module that declares tools. Recorded map[string][]string // Unheard is every runtime whose answer this index lacks: it said it was there and did not say // what it serves in time, or it answered before and not now. An address it might answer is never @@ -245,7 +245,7 @@ func findTool(tools []Tool, name string) *Tool { return nil } -// recordedModule is a module as the bus holds it: where the placement seat places it, and whether its manifest declares +// recordedModule is a module as the bus holds it: where the assigner seat places it, and whether its manifest declares // tools — what should announce itself, and where (novox/hq ADR 0571). type recordedModule struct { Module string `json:"module"` @@ -271,9 +271,9 @@ func indexOn(conn *bus.Conn, src Source, held announce.Known, before func(announ var recordsWhy []string wg.Add(2) // Which modules there are and where they are placed, and which machines the mesh has, from the bus (ADR 0571 - // clauses 4 and 5): the indexer's modules and manifests and the placement seat's placements, never any other record. + // clauses 4 and 5): the indexer's modules and manifests and the assigner seat's assignments, never any other record. go func() { defer wg.Done(); recorded, known, recordsWhy = recordsOn(src) }() - // Who holds which seat on which node, from placement (ADR 0571 clause 4): no other call. + // Who holds which seat on which node, from the assigner (ADR 0571 clause 4): no other call. go func() { defer wg.Done(); placed, placedErr = seatHoldersOn(src) }() d, err := announce.Gather(conn, held) wg.Wait() @@ -340,7 +340,7 @@ func indexOn(conn *bus.Conn, src Source, held announce.Known, before func(announ } l.NotAnswering = append(l.NotAnswering, recordsWhy...) if x.PlacedWhy != "" { - l.NotAnswering = append(l.NotAnswering, firstview.SeatHoldersRead+" (who holds which seat by placement could not be read: "+ + l.NotAnswering = append(l.NotAnswering, firstview.SeatHoldersRead+" (who holds which seat by assignment could not be read: "+ x.PlacedWhy+")") } for _, u := range x.Unheard { @@ -360,7 +360,7 @@ func indexOn(conn *bus.Conn, src Source, held announce.Known, before func(announ } // Source is where the console reads the four states of the indexer and the assigner it indexes the mesh by: the assigner's -// placement and seat-holders, the indexer's modules and manifests, by `.` (firstview.PlacementRead and the +// assignments and seat-holders, the indexer's modules and manifests, by `.` (firstview.AssignmentsRead and the // rest). The tool runner's is its first views (firstview.Views), never the owners' state (novox/hq ADR 0615 §1). type Source interface { // State is every current value of a state by key; an error says why it cannot be told yet. @@ -390,21 +390,21 @@ type manifestFacts struct { var manifestsKept sync.Map // digest → manifestFacts -// recordsOn is every module the indexer holds, with where the placement seat places it and whether it declares tools, -// and every machine placement names (moduleNames, assigner.MachineNames). What cannot be read is said, one line +// recordsOn is every module the indexer holds, with where the assigner seat places it and whether it declares tools, +// and every machine the assignments name (moduleNames, assigner.MachineNames). What cannot be read is said, one line // per state, for the listing's not answering. func recordsOn(src Source) (recorded []recordedModule, machines []string, why []string) { - placements, err := src.State(firstview.PlacementRead) + held, err := src.State(firstview.AssignmentsRead) if err != nil { - why = append(why, firstview.PlacementRead+" (where modules are placed could not be read, so what is missing cannot "+ + why = append(why, firstview.AssignmentsRead+" (where modules are placed could not be read, so what is missing cannot "+ "be said: "+err.Error()+")") } - machines = assigner.MachineNames(placements) + machines = assigner.MachineNames(held) on := map[string][]string{} - // The placement's keys in either form, a node key and its module keys or the form before (research 072 row 37). - assembled, err := assigner.PlacementsOf(placements) + // The assignments' keys in either form, a node key and its module keys or the form before (research 072 row 37). + assembled, err := assigner.AssignmentsOf(held) if err != nil { - why = append(why, firstview.PlacementRead+" (not every key is a placement: "+err.Error()+")") + why = append(why, firstview.AssignmentsRead+" (not every key is an assignment: "+err.Error()+")") } for _, node := range machines { for _, m := range assembled[node].Modules { @@ -473,7 +473,7 @@ func manifestOf(src Source, digest string) (manifestFacts, error) { return facts, nil } -// placedHolders is who holds seat (on node, for a seat held per machine) by placement, or none. +// placedHolders is who holds seat (on node, for a seat held per machine) by assignment, or none. func (x *index) placedHolders(seat, node string) []meshmoduleassigner.SeatHoldersHoldersItem { if len(x.Placed) == 0 { return nil @@ -725,7 +725,7 @@ func resolve(x *index, address string) (target, error) { for _, h := range hs { held = append(held, h.Module+" on "+h.Node) } - return target{}, fmt.Errorf("the seat %s is held by %s by placement, but no holder of it announced itself on the bus. "+ + return target{}, fmt.Errorf("the seat %s is held by %s by assignment, but no holder of it announced itself on the bus. "+ "Ask again in a moment; mesh_runtimes shows which runtimes answered", prefix, strings.Join(held, ", ")) } if len(x.Unheard) > 0 { diff --git a/node-tools/internal/console/address_test.go b/node-tools/internal/console/address_test.go index 6eb9b0f..f1ee794 100644 --- a/node-tools/internal/console/address_test.go +++ b/node-tools/internal/console/address_test.go @@ -80,7 +80,7 @@ func TestTheMeshsToolsAreFoundByAddress(t *testing.T) { t.Fatal(err) } t.Cleanup(stopNodes) - // What the mesh holds, as the indexer and placement write it (ADR 0571 clauses 4, 5): never the controller's records. + // What the mesh holds, as the indexer and the assigner write it (ADR 0571 clauses 4, 5): never the controller's records. tools := map[string][]string{"alpha": {"one", "two"}, "beta": {"three"}, "gamma": {"given"}, "delta": nil, "epsilon": {"seven"}, "mesh-module-assigner": {"nodes"}} mesh.Placed(t, tools, map[string][]string{"desk": {"alpha", "beta", "delta"}, "bench": {"epsilon", "mesh-module-assigner"}}) diff --git a/node-tools/internal/console/console_test.go b/node-tools/internal/console/console_test.go index 4a61f34..174d844 100644 --- a/node-tools/internal/console/console_test.go +++ b/node-tools/internal/console/console_test.go @@ -57,7 +57,7 @@ func TestTheConsoleListsAndCallsOverHTTP(t *testing.T) { } defer stop() - // What the mesh holds, as the indexer and placement write it (ADR 0571): ghost declares tools on desk and nothing + // What the mesh holds, as the indexer and the assigner write it (ADR 0571): ghost declares tools on desk and nothing // announces it. mesh.Placed(t, map[string][]string{"alpha": {"one", "two"}, "beta": {"three"}, "ghost": {"boo"}}, map[string][]string{"desk": {"alpha", "beta", "ghost"}}) diff --git a/node-tools/internal/console/firstviews_test.go b/node-tools/internal/console/firstviews_test.go index 20c1c17..1af9b3b 100644 --- a/node-tools/internal/console/firstviews_test.go +++ b/node-tools/internal/console/firstviews_test.go @@ -17,7 +17,7 @@ type viewer struct { } func (v *viewer) Status() []views.Status { - return []views.Status{{Owner: "mesh-delivery-assigner", Tool: "placement", State: "placement", Revision: 4, Asks: 1}} + return []views.Status{{Owner: "mesh-delivery-assigner", Tool: "assignments", State: "assignments", Revision: 4, Asks: 1}} } func (v *viewer) Again(_ context.Context, why string) []error { @@ -35,7 +35,7 @@ func TestTheConsoleShowsAndAsksAgainTheRunnersFirstViews(t *testing.T) { v := &viewer{} var recorded []map[string]any s := &Surface{src: v, who: "desk.node-tools", Record: func(a map[string]any) error { recorded = append(recorded, a); return nil }} - if got := text(s.discover(context.Background(), "mesh_first_views", nil)); !strings.Contains(got, "mesh-delivery-assigner") || !strings.Contains(got, "placement") { + if got := text(s.discover(context.Background(), "mesh_first_views", nil)); !strings.Contains(got, "mesh-delivery-assigner") || !strings.Contains(got, "assignments") { t.Errorf("mesh_first_views shows %s", got) } got := s.discover(context.Background(), "mesh_first_view_again", map[string]any{"why": "doubted"}) diff --git a/node-tools/internal/console/manifest_waits_test.go b/node-tools/internal/console/manifest_waits_test.go index 150389a..3511ec8 100644 --- a/node-tools/internal/console/manifest_waits_test.go +++ b/node-tools/internal/console/manifest_waits_test.go @@ -37,7 +37,7 @@ func TestTheManifestNamesTheFirstFamiliesOneByOne(t *testing.T) { } // A wait is no consumer (ADR 0367 §2): what it consumes is the four views families of its first views (ADR 0615 §5, issue // 1966 TLS-5) and the two events of the seat that serves the seat list (ADR 0636 §4), and nothing else. - wantConsumes := []string{"mesh-catalog.seat-definition-changed", "mesh-catalog.seat-definition-removed", "mesh-delivery-assigner.views.placement", "mesh-delivery-assigner.views.seat-holders", + wantConsumes := []string{"mesh-catalog.seat-definition-changed", "mesh-catalog.seat-definition-removed", "mesh-delivery-assigner.views.assignments", "mesh-delivery-assigner.views.seat-holders", "mesh-delivery-indexer.views.manifests", "mesh-delivery-indexer.views.modules"} if !reflect.DeepEqual(m.Consumes, wantConsumes) { t.Errorf("the tool runner consumes %v, want %v", m.Consumes, wantConsumes) diff --git a/node-tools/internal/console/mcp.go b/node-tools/internal/console/mcp.go index 685029a..1874356 100644 --- a/node-tools/internal/console/mcp.go +++ b/node-tools/internal/console/mcp.go @@ -6,7 +6,7 @@ package console import ( "context" "encoding/json" - "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" "git.novox.be/novox/mesh-sdk/go/catalogue" "os" "strings" @@ -70,7 +70,7 @@ type Surface struct { // [{module, node}]}], holders_why}`. const MethodSeats = "mesh/seats" -// seatsAnswer is MethodSeats' answer: mesh-sdk's seat definitions, with each seat's holders by placement. +// seatsAnswer is MethodSeats' answer: mesh-sdk's seat definitions, with each seat's holders by assignment. func (s *Surface) seatsAnswer() map[string]any { placed, err := seatHoldersOn(s.src) x := &index{Placed: placed} @@ -88,7 +88,7 @@ func (s *Surface) seatsAnswer() map[string]any { } out := map[string]any{"seats": seats} if err != nil { - out["holders_why"] = "who holds which seat by placement could not be read: " + err.Error() + out["holders_why"] = "who holds which seat by assignment could not be read: " + err.Error() } return out } @@ -160,7 +160,7 @@ func (s *Surface) HandleContext(ctx context.Context, r Request) *Reply { return answer(r.ID, map[string]any{}) case MethodSeats: // The seats' contract and who holds each, for a client on this machine that has no seat definitions of its own - // (the TypeScript `mesh`): read in-process from mesh-sdk and from placement, never asked of anything else + // (the TypeScript `mesh`): read in-process from mesh-sdk and from the assigner, never asked of anything else // (novox/hq ADR 0571 clauses 4 and 5). return answer(r.ID, s.seatsAnswer()) case "tools/list": diff --git a/node-tools/internal/console/runtimes_test.go b/node-tools/internal/console/runtimes_test.go index f871069..eb466e1 100644 --- a/node-tools/internal/console/runtimes_test.go +++ b/node-tools/internal/console/runtimes_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - assigner "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" - seatplacement "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + assigner "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient" + seatassigner "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" "github.com/nats-io/nats.go/micro" "github.com/novox/mesh-tools/node-tools/internal/announce" @@ -58,18 +58,18 @@ func TestARuntimeThatAnswersLateIsFoundAndOneThatNeverDoesIsNamed(t *testing.T) IndexKept, announce.Patience = time.Minute, 2500*time.Millisecond t.Cleanup(func() { IndexKept, announce.Patience = keptWas, patienceWas }) mesh := mt.New(t) - // What the mesh holds, as the indexer and placement write it (ADR 0571): never the controller's records. + // What the mesh holds, as the indexer and the assigner write it (ADR 0571): never the controller's records. mesh.Placed(t, map[string][]string{"slack": {"slack_check"}, "nap": {"doze"}, "nextcloud-client": {"nextcloud_check"}}, map[string][]string{"laptop": {"slack", "nextcloud-client"}, "sleeper": {"nap", "nextcloud-client"}, "desktop": {"nextcloud-client"}, "bench": nil}) - // Who holds which seat, by placement (ADR 0571 clause 4), as the seat mesh-module-assigner's holder composes it. + // Who holds which seat, by assignment (ADR 0571 clause 4), as the seat mesh-module-assigner's holder composes it. placedKV := mesh.Bucket(t, meshtest.SeatHoldersBucket) holdersKey, err := assigner.SeatHoldersKey("mesh-wants", "") if err != nil { t.Fatal(err) } - raw, _ := json.Marshal(seatplacement.SeatHolders{V: assigner.Version, Seat: "mesh-wants", Scope: "mesh", - Holders: []seatplacement.SeatHoldersHoldersItem{{Module: "mesh-delivery-assigner", Node: "bench"}}}) + raw, _ := json.Marshal(seatassigner.SeatHolders{V: assigner.Version, Seat: "mesh-wants", Scope: "mesh", + Holders: []seatassigner.SeatHoldersHoldersItem{{Module: "mesh-delivery-assigner", Node: "bench"}}}) if _, err := placedKV.Put(holdersKey, raw); err != nil { t.Fatal(err) } @@ -158,8 +158,8 @@ func TestARuntimeThatAnswersLateIsFoundAndOneThatNeverDoesIsNamed(t *testing.T) // The silent one is named, never called missing. for address, want := range map[string]string{ - // A seat whose holder announced nothing is named with its holder by placement, never called missing. - "mesh-wants.read": "the seat mesh-wants is held by mesh-delivery-assigner on bench by placement", + // A seat whose holder announced nothing is named with its holder by assignment, never called missing. + "mesh-wants.read": "the seat mesh-wants is held by mesh-delivery-assigner on bench by assignment", "sleeper/nap.doze": "nap is assigned to sleeper in the mesh's records, but nothing that answered discovery serves it: discovery did not hear in full from node-tools on sleeper (it answered PING", "sleeper/nextcloud-client.nextcloud_check": "nextcloud-client on sleeper did not answer discovery: discovery did not hear in full from node-tools on sleeper", } { diff --git a/node-tools/internal/firstview/firstview.go b/node-tools/internal/firstview/firstview.go index 6ae8b05..4b93e15 100644 --- a/node-tools/internal/firstview/firstview.go +++ b/node-tools/internal/firstview/firstview.go @@ -1,5 +1,5 @@ // Package firstview is the tool runner's picture of the four states it reads of the indexer and the assigner: the assigner's -// placement and seat-holders, the indexer's manifests and modules (novox/hq ADR 0615 §1, §3; ADR 0621 §2; issue 1966 TLS-5). +// assignments and seat-holders, the indexer's manifests and modules (novox/hq ADR 0615 §1, §3; ADR 0621 §2; issue 1966 TLS-5). // // **It never reads the owners' state.** At start it asks each owner's first-view tool until answered (the owner answers in a // runtime of its own, never through this one: ADR 0621 §1), then follows the owner's views family, one event per changed key; @@ -32,7 +32,7 @@ const ( // The names the console reads the four states by (`.`), as the manifest's `consumes` names their views // families (no seat's client names a holder, novox/hq ADR 0625 §4; TestTheFirstViewsAreTheManifestsViews). const ( - PlacementRead = Assigner + ".placement" + AssignmentsRead = Assigner + ".assignments" SeatHoldersRead = Assigner + ".seat-holders" ModulesRead = Indexer + ".modules" ManifestsRead = Indexer + ".manifests" @@ -43,13 +43,13 @@ type Spec struct{ Owner, Tool, State string } // Specs are the four. var Specs = []Spec{ - {Assigner, "placement", "placement"}, + {Assigner, "assignments", "assignments"}, {Assigner, "seat-holders", "seat-holders"}, {Indexer, "manifests", "manifests"}, {Indexer, "modules", "modules"}, } -// Name is the name a state is read by, `.`: PlacementRead, SeatHoldersRead and the indexer's. +// Name is the name a state is read by, `.`: AssignmentsRead, SeatHoldersRead and the indexer's. func (s Spec) Name() string { return s.Owner + "." + s.State } // Views is the four followers. diff --git a/node-tools/internal/firstview/firstview_integration_test.go b/node-tools/internal/firstview/firstview_integration_test.go index a7972dc..baa369d 100644 --- a/node-tools/internal/firstview/firstview_integration_test.go +++ b/node-tools/internal/firstview/firstview_integration_test.go @@ -92,7 +92,7 @@ func TestTheRunnersConsumerCarriesTheOwnersViewsFamiliesWhenTheOwnersAreDownThen t.Cleanup(stop) // The owners are down: no tool answers, nothing is claimed, and past the bound each view is a finding. - if _, err := v.State(Assigner + ".placement"); err == nil { + if _, err := v.State(Assigner + ".assignments"); err == nil { t.Fatal("a state its owner has not answered is claimed") } mt.Until(t, func() error { diff --git a/node-tools/internal/firstview/firstview_test.go b/node-tools/internal/firstview/firstview_test.go index 9911e09..11c299d 100644 --- a/node-tools/internal/firstview/firstview_test.go +++ b/node-tools/internal/firstview/firstview_test.go @@ -28,9 +28,9 @@ type owners struct { } func newOwners() *owners { - return &owners{state: map[string]map[string]string{"placement": {"anchor": `{"p":1}`}, "seat-holders": {"seat": `{"h":1}`}, + return &owners{state: map[string]map[string]string{"assignments": {"anchor": `{"p":1}`}, "seat-holders": {"seat": `{"h":1}`}, "manifests": {"d1": `{"m":1}`}, "modules": {"web": `{"w":1}`}}, - rev: map[string]uint64{"placement": 4, "seat-holders": 2, "manifests": 7, "modules": 3}, asked: map[string]int{}, finds: map[string]bool{}} + rev: map[string]uint64{"assignments": 4, "seat-holders": 2, "manifests": 7, "modules": 3}, asked: map[string]int{}, finds: map[string]bool{}} } func (o *owners) ask(address string, _ any) (json.RawMessage, error) { @@ -104,7 +104,7 @@ func TestTheRunnerHoldsTheFourStatesFromTheOwnersFirstViewsAndTheirEvents(t *tes defer stop() // Down: nothing is claimed, and past the bound each unanswered view is a finding. - if _, err := v.State("mesh-delivery-assigner.placement"); err == nil || !strings.Contains(err.Error(), "not been answered") { + if _, err := v.State("mesh-delivery-assigner.assignments"); err == nil || !strings.Contains(err.Error(), "not been answered") { t.Fatalf("a state its owner has not answered is claimed: %v", err) } eventually(t, "no finding past the bound", func() bool { o.mu.Lock(); defer o.mu.Unlock(); return len(o.finds) == 4 }) @@ -124,31 +124,31 @@ func TestTheRunnerHoldsTheFourStatesFromTheOwnersFirstViewsAndTheirEvents(t *tes // Events: the next revision is applied; an old one passed over; a deletion removes; none of it asks again. asked := func(tool string) int { o.mu.Lock(); defer o.mu.Unlock(); return o.asked[tool] } - before := asked("placement") - o.say(t, "placement", "laptop", `{"p":2}`, 5, false) - o.say(t, "placement", "laptop", `{"p":0}`, 5, false) - o.say(t, "placement", "anchor", "", 6, false) + before := asked("assignments") + o.say(t, "assignments", "laptop", `{"p":2}`, 5, false) + o.say(t, "assignments", "laptop", `{"p":0}`, 5, false) + o.say(t, "assignments", "anchor", "", 6, false) // (a deleted mark carries no value: Deleted is the encoding's, set below) - if got, _ := v.Entry("mesh-delivery-assigner.placement", "laptop"); string(got) != `{"p":2}` { + if got, _ := v.Entry("mesh-delivery-assigner.assignments", "laptop"); string(got) != `{"p":2}` { t.Errorf("the next revision is not applied: %q", got) } - if n := asked("placement"); n != before { + if n := asked("assignments"); n != before { t.Errorf("an event in order asked the first view again (%d asks, was %d)", n, before) } // A gap (revision 9 where 7 was next) asks the first view once more, said in the log. - o.say(t, "placement", "x", `{"p":9}`, 9, false) - eventually(t, "a gap did not ask the first view again", func() bool { return asked("placement") > before }) + o.say(t, "assignments", "x", `{"p":9}`, 9, false) + eventually(t, "a gap did not ask the first view again", func() bool { return asked("assignments") > before }) // The status says owner, tool, revision and the asks; the hand ask asks every view again. - var placement views.Status + var assignments views.Status for _, s := range v.Status() { - if s.State == "placement" { - placement = s + if s.State == "assignments" { + assignments = s } } - if placement.Owner != "mesh-delivery-assigner" || placement.Tool != "placement" || placement.Asks < 2 || placement.Answered.IsZero() { - t.Errorf("the status of placement is %+v", placement) + if assignments.Owner != "mesh-delivery-assigner" || assignments.Tool != "assignments" || assignments.Asks < 2 || assignments.Answered.IsZero() { + t.Errorf("the status of assignments is %+v", assignments) } manifests := asked("manifests") if errs := v.Again(context.Background(), "doubted"); len(errs) != 0 { @@ -181,7 +181,7 @@ func TestTheFirstViewsAreTheManifestsViews(t *testing.T) { if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } - want := map[string]bool{PlacementRead: true, SeatHoldersRead: true, ModulesRead: true, ManifestsRead: true} + want := map[string]bool{AssignmentsRead: true, SeatHoldersRead: true, ModulesRead: true, ManifestsRead: true} for _, s := range Specs { if !want[s.Name()] { t.Errorf("the first view %s is read by no name here", s.Name()) diff --git a/node-tools/internal/meshtest/meshtest.go b/node-tools/internal/meshtest/meshtest.go index b106673..2f021e1 100644 --- a/node-tools/internal/meshtest/meshtest.go +++ b/node-tools/internal/meshtest/meshtest.go @@ -21,8 +21,8 @@ import ( "testing" "time" - assigner "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" - seatplacement "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + assigner "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient" + seatassigner "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" meshcatalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" meshcatalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" "git.novox.be/novox/mesh-sdk/go/membership" @@ -158,18 +158,18 @@ func sdkMembership(t *testing.T, mem bus.Membership) membership.Membership { const ( indexer = "mesh-delivery-indexer" assignerHolder = "mesh-delivery-assigner" - // PlacementBucket and SeatHoldersBucket are the assigner's states placement and seat-holders. - PlacementBucket = assignerHolder + "_placement" + // AssignmentsBucket and SeatHoldersBucket are the assigner's states assignments and seat-holders. + AssignmentsBucket = assignerHolder + "_assignments" SeatHoldersBucket = assignerHolder + "_seat-holders" ModulesBucket = indexer + "_modules" ManifestsBucket = indexer + "_manifests" ) // ConsoleReads are the states a console's runtime reads to say what the mesh holds (novox/hq ADR 0571 clauses 4, 5): -// placement, the indexer's modules and manifests, and the seat holders. +// assignments, the indexer's modules and manifests, and the seat holders. func ConsoleReads() []bus.StateIssued { return []bus.StateIssued{ - {Name: assignerHolder + ".placement", Bucket: PlacementBucket}, + {Name: assignerHolder + ".assignments", Bucket: AssignmentsBucket}, {Name: indexer + ".modules", Bucket: ModulesBucket}, {Name: indexer + ".manifests", Bucket: ManifestsBucket}, {Name: assignerHolder + ".seat-holders", Bucket: SeatHoldersBucket}, @@ -177,7 +177,7 @@ func ConsoleReads() []bus.StateIssued { } // Placed writes what the mesh holds as its parts write it, with mesh-sdk's encoders: each module the indexer holds with -// its manifest (tools, the tools it declares; none for a module without), and each node's placement of modules. +// its manifest (tools, the tools it declares; none for a module without), and each node's assignment of modules. func (m *Mesh) Placed(t *testing.T, tools map[string][]string, on map[string][]string) { t.Helper() kv := func(bucket string) nats.KeyValue { @@ -188,7 +188,7 @@ func (m *Mesh) Placed(t *testing.T, tools map[string][]string, on map[string][]s } return b } - modules, manifests, placement := kv(ModulesBucket), kv(ManifestsBucket), kv(PlacementBucket) + modules, manifests, assigned := kv(ModulesBucket), kv(ManifestsBucket), kv(AssignmentsBucket) kv(SeatHoldersBucket) for module, declared := range tools { manifest, _ := json.Marshal(map[string]any{"module": module, "tools": declared}) @@ -210,17 +210,17 @@ func (m *Mesh) Placed(t *testing.T, tools map[string][]string, on map[string][]s } } for node, placed := range on { - p := seatplacement.Placement{V: assigner.Version, Node: node} + p := seatassigner.Assignments{V: assigner.Version, Node: node} for _, module := range placed { - p.Modules = append(p.Modules, seatplacement.PlacedModule{Module: module}) + p.Modules = append(p.Modules, seatassigner.PlacedModule{Module: module}) } // As the seat writes it: its node key and a key per module (research 072 row 37). - values, err := assigner.PlacementValues(p) + values, err := assigner.AssignmentsValues(p) if err != nil { t.Fatal(err) } for key, raw := range values { - if _, err := placement.Put(key, raw); err != nil { + if _, err := assigned.Put(key, raw); err != nil { t.Fatal(err) } } diff --git a/node-tools/module.json b/node-tools/module.json index 08b4f05..f490158 100644 --- a/node-tools/module.json +++ b/node-tools/module.json @@ -73,7 +73,7 @@ "consumes": [ "mesh-catalog.seat-definition-changed", "mesh-catalog.seat-definition-removed", - "mesh-delivery-assigner.views.placement", + "mesh-delivery-assigner.views.assignments", "mesh-delivery-assigner.views.seat-holders", "mesh-delivery-indexer.views.manifests", "mesh-delivery-indexer.views.modules"