Review round 2: a held module's object reads come from its running manifest; one with none keeps the list in force, said; indexer_judge asks the engine for the running build again (issue 774)
mesh/delivery-group group feat/l3a-waits rejected: composed together: the checker's verdict at the members' heads (de2cdacb9cde): shanks
mesh/check failed (3): shanks: novox/mesh-sdk#163 does not merge into the trunk: files in conflict: go/deli…; and 2 more | 83f7a7612d19 on c4470f42dba9
mesh/delivery closed: the pull request closed unmerged
mesh/delivery-group group feat/l3a-waits rejected: composed together: the checker's verdict at the members' heads (de2cdacb9cde): shanks
mesh/check failed (3): shanks: novox/mesh-sdk#163 does not merge into the trunk: files in conflict: go/deli…; and 2 more | 83f7a7612d19 on c4470f42dba9
mesh/delivery closed: the pull request closed unmerged
This commit is contained in:
@@ -362,6 +362,8 @@ func (ix *Indexer) JudgeAgain(ctx context.Context, module string) TakenIn {
|
||||
out.Answer = "the indexer holds no manifest of " + module
|
||||
return out
|
||||
}
|
||||
// The build this program runs is asked again, so a start pass that missed the engine's answer is recovered without a restart.
|
||||
ix.learnOwnBuild(ctx)
|
||||
if _, err := ix.JudgeAll(ctx, nil); err != nil {
|
||||
out.Answer = "the manifests could not be judged: " + err.Error()
|
||||
return out
|
||||
|
||||
@@ -175,7 +175,15 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if rows, _ := ListVerdicts(keys, get, "", true); len(rows) <= len(keys)-3 || rows[0].Module > rows[len(rows)-1].Module {
|
||||
t.Fatalf("indexer_verdicts, all: %d rows of %d verdicts", len(rows), len(keys))
|
||||
}
|
||||
// indexer_judge asks the engine for the running build again: a start pass that missed it is recovered (the trunk's value of
|
||||
// the indexer is the newer one, so the field waits; asked and answered with that same build it is refused).
|
||||
ix.ownFP = ""
|
||||
ix.OwnBuild = func(context.Context) (string, error) { return "src2:" + strings.Repeat("a", 64), nil }
|
||||
if got := ix.JudgeAgain(ctx, "later"); !got.Stored || !strings.Contains(got.Answer, "refused") || ix.ownFP == "" {
|
||||
t.Fatalf("indexer_judge did not learn the running build: %+v", got)
|
||||
}
|
||||
ix.ownFP = ownFP
|
||||
ix.OwnBuild = nil
|
||||
if got := ix.JudgeAgain(ctx, "later"); !got.Stored || !strings.Contains(got.Answer, "waits") || !strings.Contains(got.Answer, "a-field-from-later") {
|
||||
t.Fatalf("indexer_judge: %+v", got)
|
||||
}
|
||||
|
||||
@@ -680,6 +680,22 @@ func TestGrants(t *testing.T) {
|
||||
if slices.Contains(web.Publish, "$JS.API.DIRECT.GET.KV_mesh-knowledge_sections.>") {
|
||||
t.Error("the object bucket's read is granted as a state's")
|
||||
}
|
||||
// ADR 0601 clause 3: the owner's trunk manifest now waits for a field; its running build's manifest still declares the
|
||||
// bucket, so web keeps its object grant.
|
||||
fp := "src2:" + strings.Repeat("cd", 32)
|
||||
b.put(grants.ReadModules, "mesh-knowledge", delivery.Module{V: delivery.Version, FP2: "src2:" + strings.Repeat("ab", 32),
|
||||
Manifest: delivery.ManifestDigest([]byte(`{"module":"mesh-knowledge","version":"2"}`)), Repository: "novox/x", Commit: "c",
|
||||
Verdict: delivery.VerdictRefused, Problems: []string{"it waits"}, Unknown: []string{"core-credentials"}})
|
||||
b.put(grants.ReadHave, "a.mesh-knowledge", delivery.Have{V: delivery.Version, Phase: delivery.PhaseRunning, Health: delivery.HealthOK, FP: fp})
|
||||
heldKey, _ := delivery.BuilderBuildKey("mesh-knowledge", fp)
|
||||
b.put(grants.ReadBuilds, heldKey, map[string]any{"v": delivery.Version, "state": "done", "manifest": delivery.ManifestDigest([]byte(knowledge))})
|
||||
if heldWeb := (func() grants.User {
|
||||
us := shadowOf(t, b)
|
||||
return us[slices.IndexFunc(us, func(u grants.User) bool { return u.User == "a.web" })]
|
||||
})(); !slices.Contains(heldWeb.Publish, read) {
|
||||
t.Errorf("a reader of a held module's object store lost its grant: %v", heldWeb.Publish)
|
||||
}
|
||||
b.manifestOf("mesh-knowledge", knowledge) // accepted again for the rest of the row
|
||||
// ADR 0592 §6, §25: the bucket past 75 percent of its cap is said, in one warning, and cleared once below; the history
|
||||
// stream at 10 percent is not.
|
||||
var said []asks.Condition
|
||||
@@ -2736,6 +2752,11 @@ func TestGrants(t *testing.T) {
|
||||
}
|
||||
b.put(grants.ReadHave, "a.nats", delivery.Have{V: delivery.Version, Phase: delivery.PhaseRunning, Health: delivery.HealthOK,
|
||||
UserList: &delivery.UserListWritten{Source: "a.nats.src2", Revision: 7, Digest: "sha256:aa", Users: 5, Key: busKey.PublicKey}})
|
||||
// mod-r runs a build whose manifest is the accepted one: the held module's seats and streams are composed from it.
|
||||
runFP := "src2:" + strings.Repeat("cd", 32)
|
||||
b.put(grants.ReadHave, "b.mod-r", delivery.Have{V: delivery.Version, Phase: delivery.PhaseRunning, Health: delivery.HealthOK, FP: runFP})
|
||||
runKey, _ := delivery.BuilderBuildKey("mod-r", runFP)
|
||||
b.put(grants.ReadBuilds, runKey, map[string]any{"v": delivery.Version, "state": "done", "manifest": delivery.ManifestDigest([]byte(ctl))})
|
||||
p := partOn(b)
|
||||
p.Objects = &fakeObjects{}
|
||||
var said []asks.Condition
|
||||
@@ -2777,6 +2798,18 @@ func TestGrants(t *testing.T) {
|
||||
t.Errorf("%s: the kept user was not said: %+v", held.name, last)
|
||||
}
|
||||
}
|
||||
// A held module that runs no build the part can read declares nothing to anyone: the list in force is kept, said.
|
||||
delete(b.states[grants.ReadHave], "b.mod-r")
|
||||
b.put(grants.ReadModules, "mod-r", delivery.Module{V: delivery.Version, FP2: "src2:" + strings.Repeat("ab", 32),
|
||||
Manifest: delivery.ManifestDigest([]byte(ctl)), Repository: "novox/x", Commit: "c", Verdict: delivery.VerdictRefused,
|
||||
Problems: []string{"it is held"}, Unknown: []string{"core-credentials"}})
|
||||
b.put(grants.ReadAccounts, "a.mod-x", map[string]any{"user": "a.mod-x", "hash": "$2a$10$gen9", "generation": 9, "fingerprint": "sha256:9"})
|
||||
wasList, _, _ := p.Sealed()
|
||||
res := p.Compose()
|
||||
nowList, _, _ := p.Sealed()
|
||||
if nowList.Digest != wasList.Digest || res.Sealed == nil || !strings.Contains(res.Sealed.Why, "running manifest of mod-r") {
|
||||
t.Errorf("a held module with no running manifest did not keep the list in force: %+v", res.Sealed)
|
||||
}
|
||||
// Accepted again: the users compose from the manifest and the condition clears.
|
||||
b.manifestOf("mod-r", ctl)
|
||||
if p.Compose(); said[len(said)-1].State != asks.StateCleared {
|
||||
|
||||
@@ -445,6 +445,22 @@ func ReadInputs(r Reader, cache *Manifests) Inputs {
|
||||
in.Gaps = append(in.Gaps, Gap{Input: "wanted manifests", Why: "no build record names the manifest at the wanted fingerprint, so the trunk's is used: " + strings.Join(fromTrunk, ", ")})
|
||||
}
|
||||
in.Held = heldManifests(r, in, cache)
|
||||
// A held module placed on a node whose running manifest is not found declares no seat, stream or object bucket to
|
||||
// anyone: composing past it would drop the grants of those who use them, so the list in force is kept (ADR 0601
|
||||
// clause 3), and the gap says which module and why.
|
||||
for _, g := range in.Refused {
|
||||
module, ok := strings.CutPrefix(g.Input, "manifest of ")
|
||||
if _, found := in.Held[module]; !ok || found {
|
||||
continue
|
||||
}
|
||||
for _, assigned := range in.Assigned {
|
||||
if slices.Contains(assigned, module) {
|
||||
in.Gaps = append(in.Gaps, Gap{Input: "running manifest of " + module, Failed: true,
|
||||
Why: "its manifest is held and no running build's manifest is found, so the seats and streams it declares cannot be composed: the list in force is kept"})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
in.Hashes = readHashes(r, &in.Gaps)
|
||||
// The seat mesh-enrolment's keys are every token since the controller's end (issue 1126).
|
||||
in.Enrolling, _ = readEnrolling(r, &in.Gaps)
|
||||
|
||||
@@ -81,7 +81,7 @@ func records(in Inputs, union bool) (buscompose.Records, []Gap) {
|
||||
d.KeyedReads = append(d.KeyedReads, buscompose.KeyedRead{Read: sr.Read, Key: sr.Key})
|
||||
}
|
||||
d.Hears, d.HearsAStream, d.Consumes = hearsOf(m, declared, node, values, d.Consumes)
|
||||
d.Reads, d.ReadsObjects, d.ReadsRefused = readsOfObjects(m.Module, node, d.Reads, d.ReadsRefused, in.Manifests, values)
|
||||
d.Reads, d.ReadsObjects, d.ReadsRefused = readsOfObjects(m.Module, node, d.Reads, d.ReadsRefused, declared, values)
|
||||
return d
|
||||
}
|
||||
d := declare(m)
|
||||
|
||||
Reference in New Issue
Block a user