S3: the indexer takes its own build from MESH_FINGERPRINT first

Builds: design 47 G A-366

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-13 20:37:25 +01:00
parent bac26c8a28
commit b2bddecde2
3 changed files with 34 additions and 1 deletions
@@ -462,7 +462,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
Predefined: awaitedStore{b: predefined}, ConfigCandidates: awaitedStore{b: configCandidates}, Logf: logger.Printf,
Named: namedVia(calls.Call), Trunk: trunkVia(calls.Call), Contains: containsVia(calls.Call), Read: readVia(calls.Call),
ReadOpen: openVia(calls.Call), Packages: awaitedStore{b: packages, js: js, name: index.Bucket(cred.Module, index.PackagesState)}, Files: filesVia(calls.Call), GoSum: goSumVia(calls.Call), GoMod: goModVia(calls.Call),
OwnBuild: ownBuildVia(calls.Call, cred.Module, cred.Node), OwnBuildState: awaitedStore{b: ownBuildState}, Heard: heardStore, Placement: placementVia(calls.CallKept), RunningWhole: runningWholeVia(js), Runs: awaitedStore{b: runs}, Graph: graph,
OwnBuild: ownBuildFirst(process.OwnBuild(), ownBuildVia(calls.Call, cred.Module, cred.Node)), OwnBuildState: awaitedStore{b: ownBuildState}, Heard: heardStore, Placement: placementVia(calls.CallKept), RunningWhole: runningWholeVia(js), Runs: awaitedStore{b: runs}, Graph: graph,
SeatDefinitions: awaitedStore{b: seatDefs}, ReadFile: readFileVia(calls.Call), SaySeatDefinition: saySeats,
Revisions: revisions, EntryIndex: awaitedStore{b: process.AwaitBucket(ctx, js, conn, index.Bucket(cred.Module, index.EntryIndexState), "no entry is found by its fingerprint", logger.Printf)}, // Message a kept call: a read, called again through a transport fault (ADR 0668 §1)
// Each catalog revision may bring another holder of a build seat: the build modules are found again (buildmodules.go).
@@ -7,6 +7,7 @@ import (
"fmt"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/git"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshpipelinerunner"
"git.novox.be/novox/mesh-sdk/go/process"
"mesh-delivery-indexer/internal/index"
"slices"
"strings"
@@ -125,6 +126,25 @@ func TestTheTrunkIsTheDirectoriesTheForgeListsTrees(t *testing.T) { // 1900/AC3
t.Errorf("%s: own build = %q %v, want %q", row.name, fp, err, row.want)
}
}
// Design 47 G A-366: a process started with a fingerprint takes it and asks no engine; one started without asks the engine.
for _, row := range []struct {
name string
started process.Build
want string
wantAsked bool
}{
{"started with a fingerprint", process.Build{Fingerprint: "src2:env"}, "src2:env", false},
{"started without one", process.Build{Unknown: process.OwnBuildUnknown}, "src2:abc", true},
} {
called := false
ask := func(string, any) (json.RawMessage, error) {
called = true
return json.RawMessage(`{"runs":{"fp":"src2:abc"}}`), nil
}
if fp, err := ownBuildFirst(row.started, ownBuildVia(ask, "acme-indexer", "n1"))(context.Background()); err != nil || fp != row.want || called != row.wantAsked {
t.Errorf("%s: own build = %q %v, engine asked %v, want %q asked %v", row.name, fp, err, called, row.want, row.wantAsked)
}
}
none := func(string, any) (json.RawMessage, error) { return json.RawMessage(`{}`), nil }
if _, err := ownBuildVia(none, "acme-indexer", "n1")(context.Background()); err == nil {
t.Error("an engine that says nothing runs gave a build")
@@ -5,6 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"
"git.novox.be/novox/mesh-sdk/go/process"
)
// compositionVerb is the node-engine seat's read verb that says what runs of a module on a machine (its Runs.FP), asked of
@@ -12,6 +14,17 @@ import (
// from the trunk's value of itself or the haves bucket.
const compositionVerb = "seat:node-engine.composition"
// ownBuildFirst is the build the process was started with (mesh-sdk process.OwnBuild: MESH_FINGERPRINT, set by the node-engine
// and by a unit started by hand); only when it is unset does it ask the engine through ask (design 47 G A-366).
func ownBuildFirst(started process.Build, ask func(ctx context.Context) (string, error)) func(ctx context.Context) (string, error) {
return func(ctx context.Context) (string, error) {
if started.Fingerprint != "" {
return started.Fingerprint, nil
}
return ask(ctx)
}
}
// ownBuildVia asks the engine of node which fingerprint of the indexer runs there.
func ownBuildVia(call toolCaller, module, node string) func(ctx context.Context) (string, error) {
return func(context.Context) (string, error) {