W13.8: the node-engine fetches a kept build through the build node's kept-artifact, the node taken from the want's kept-on

A want that names a node in kept-on, for an artifact its parts name, is fetched through kept-artifact of that node's build seat and
read as an object on the bus, checked against the digest; with no kept-on it is fetched from the store, and the builder's builds
are read no more (the apply hook, the fetch and the object read from bc8fbc7, its node and fingerprint from the want).

Builds: design 47 G §271, §526, §421 (A-50)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-11 23:39:36 +01:00
parent 38e13ef030
commit 5173f2a31c
11 changed files with 353 additions and 4 deletions
+31
View File
@@ -0,0 +1,31 @@
package selfcompose
import (
"context"
"strings"
)
// KeptBuildOf is the node that keeps the build a module is wanted at, and its fingerprint, for the artifact store's
// holder (design 47 G section 271, 526, A-50): the want's `kept-on` and nothing else names it, the builder's builds being
// no read of the node-engine's (section 421). kept is false when the module has no want, its want names no keeping node,
// or its `parts` do not name the digest ("sha256:" and 64 hex digits, or bare): the artifact is then fetched from the store.
func (c *Composer) KeptBuildOf(_ context.Context, module, digest string) (node, fp string, kept bool, err error) {
c.mu.Lock()
w, ok := c.wants[module]
c.mu.Unlock()
if !ok || w.Fp == "" || w.KeptOn == "" {
return "", "", false, nil
}
if len(w.Parts) > 0 {
named := false
for _, d := range w.Parts {
if strings.TrimPrefix(d, "sha256:") == strings.TrimPrefix(digest, "sha256:") {
named = true
}
}
if !named {
return "", "", false, nil
}
}
return w.KeptOn, w.Fp, true, nil
}
+35
View File
@@ -0,0 +1,35 @@
package selfcompose
import (
"context"
"strings"
"testing"
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshwants"
)
// The node that keeps a kept build is the want's kept-on alone, for an artifact its parts name (design 47 G 526, A-50).
func TestTheKeepingNodeIsTheWantsKeptOn(t *testing.T) {
kd := strings.Repeat("6", 64)
for _, row := range []struct {
name, digest string
want *meshwants.WantsByWantNodeModuleValue
node string
kept bool
}{
{"kept, by its bare digest", kd, &meshwants.WantsByWantNodeModuleValue{Fp: "f1", KeptOn: "n3", Parts: map[string]string{"db:p": "sha256:" + kd}}, "n3", true},
{"kept, by the declared digest", "sha256:" + kd, &meshwants.WantsByWantNodeModuleValue{Fp: "f1", KeptOn: "n3", Parts: map[string]string{"db:p": "sha256:" + kd}}, "n3", true},
{"a digest the parts do not name", "sha256:" + strings.Repeat("7", 64), &meshwants.WantsByWantNodeModuleValue{Fp: "f1", KeptOn: "n3", Parts: map[string]string{"db:p": "sha256:" + kd}}, "", false},
{"a want naming no keeping node", kd, &meshwants.WantsByWantNodeModuleValue{Fp: "f1", Parts: map[string]string{"db:p": "sha256:" + kd}}, "", false},
{"no want of the module", kd, nil, "", false},
} {
c := &Composer{wants: map[string]meshwants.WantsByWantNodeModuleValue{}}
if row.want != nil {
c.wants["db"] = *row.want
}
node, fp, kept, err := c.KeptBuildOf(context.Background(), "db", row.digest)
if err != nil || node != row.node || kept != row.kept || (kept && fp != "f1") {
t.Errorf("%s: node %q fp %q kept %v err %v", row.name, node, fp, kept, err)
}
}
}