Let only a module's wanted or newest composition hold the node's own apply back, never a stale refused one (issue 1945)
mesh/delivery merged: source.main moved to novox/mesh-host@cf455bc4fe3e
mesh/check pass ecf142e4513f on cf455bc4fe3e | unit 292 run, 1033 kept, 5 skipped | integration 295 run, 1034 kept, 4 skipped | over bound: unit (slow…

This commit is contained in:
2026-10-25 02:01:24 +01:00
parent fa9e4483c8
commit ecf142e451
2 changed files with 49 additions and 6 deletions
+27 -6
View File
@@ -393,18 +393,39 @@ func (a *Agent) others(except string) []delivery.Composed {
}
// unreadableModules are the keys of the module compositions in the node's bucket that cannot be read or are refused, of a
// module the assigner has not removed. Called holding a.mu.
// module the assigner has not removed: for each module only the composition its want names, else its newest, since a
// stale one nobody applies (written before a rule the SDK now holds) must not hold the node's own back. Called holding
// a.mu.
func (a *Agent) unreadableModules() []string {
var out []string
type pick struct {
key string
c compNow
}
current := map[string]pick{}
for key, c := range a.comps {
_, m, _, isNode, err := delivery.ParseComposedKey(key)
if err != nil || isNode || c.Err == nil {
_, m, fp, isNode, err := delivery.ParseComposedKey(key)
if err != nil || isNode {
continue
}
if w := a.wants[m]; w.Present && w.Want.Removed {
w := a.wants[m]
if w.Present && w.Want.Removed {
continue
}
out = append(out, key)
if w.Present && w.Want.FP != "" {
if w.Want.FP == fp {
current[m] = pick{key, c}
}
continue
}
if prev, ok := current[m]; !ok || c.Rev > prev.c.Rev {
current[m] = pick{key, c}
}
}
var out []string
for _, p := range current {
if p.c.Err != nil {
out = append(out, p.key)
}
}
sort.Strings(out)
return out
+22
View File
@@ -760,3 +760,25 @@ func TestTheNodesOwnWaitsWhileAModulesCompositionCannotBeRead(t *testing.T) {
b.comps.put(gk, graw)
eventually(t, "the node's own not applied", func() bool { return len(b.appliedList()) == 1 })
}
// A stale refused composition beside a newer readable one of the same module does not hold the node's own apply back:
// only the composition the module's want names, else its newest, counts (the review of issue 1945: the bucket keeps
// compositions written before the filled paths, which the SDK now refuses, and nobody applies them).
func TestAStaleRefusedCompositionDoesNotHoldTheNodesOwnBack(t *testing.T) {
b := newBed(t)
stale, err := delivery.ComposedKey(node, "power", fpOf("a"))
if err != nil {
t.Fatal(err)
}
b.comps.before(stale, []byte(`{"v":1,"not":"a composition"}`))
gk, graw, _ := composition(t, "power", fpOf("b"), false, file("power", "x", "1"))
b.comps.before(gk, graw)
nk, nraw, ndig := composition(t, NodeModule, "", false)
nwk, _ := delivery.WantNodeKey(node)
nwraw, _ := delivery.EncodeNodeWant(delivery.NodeWant{Composed: ndig})
b.comps.before(nk, nraw)
b.wants.before(nwk, nwraw)
stop := b.run()
defer stop()
eventually(t, "the node's own not applied", func() bool { return len(b.appliedList()) == 1 })
}