Compose again when a wanted build lands, so a node that waited on a build is not left refused until another input moves (issue 774)
mesh/delivery merged: source.main moved to novox/mesh-host@b133a8949dcb
mesh/delivery-group group fix/build-not-done-holds-one-module merged: every member is merged
mesh/check checking 33131dcbfe77 on 2ae7c53376e8 | novox/mesh-host#181 in group fix/build-not-done-holds-one-module

At 19:30 on 2026-10-30 node-tools' want moved to a build not yet done; once it landed, ace, g14 and shanks stayed
refused until some other input moved (g14 and shanks at 19:40, ace after a restart), since the composer watched no
build.

Quick fix: compose again on a timer while anything is held. Thorough fix: the composer watches the builder's builds
(within the node's compose reads, NodeComposeReads) and makes a pass when a done build of a module the node wants, at
its want's or the trunk's build, lands; nothing else moves it. With mesh-sdk 9685990a (pinned here) a running module
whose build is not done is held, keeping what runs, so the pass that waited composes it as soon as it lands. Chose
thorough: event-driven, no poll.
This commit is contained in:
2026-10-30 19:49:08 +01:00
parent 4055e0094b
commit 33131dcbfe
4 changed files with 126 additions and 5 deletions
+24
View File
@@ -180,9 +180,33 @@ func (c *Composer) inputs() []input {
{delivery.HaveBucket, node + ".>", nil, (*Composer).takeModuleHave},
{delivery.ModulesBucket, ">", (*Composer).takeModule, nil},
{ResolvedBucket, node + ".>", (*Composer).takeValue, nil},
// The builder's builds: a pass that held a module for a build not yet done is made again when it lands (issue
// 774, 2026-10-30 19:30: node-tools' build landed and ace, g14 and shanks stayed refused until another input moved).
{delivery.BuilderBuildsBucket, ">", nil, (*Composer).takeBuildDone},
}
}
// takeBuildDone says whether a build that landed is one this node composes from: done, of a module it wants at that
// build or whose trunk's build it is. Every other build, and a build not done, moves nothing.
func (c *Composer) takeBuildDone(u agent.Update) bool {
if u.Deleted {
return false
}
module, fp, err := delivery.ParseBuilderBuildKey(u.Key)
if err != nil {
return false
}
c.mu.Lock()
w, wanted := c.wants[module]
m := c.modules[module]
c.mu.Unlock()
if !wanted || (w.FP != fp && m.FP2 != fp) {
return false
}
b, err := delivery.DecodeBuilderBuild(u.Value)
return err == nil && b.State == delivery.BuildDone
}
// Watch starts the composer and answers the compositions it makes: each as a key of `composed-<node>` would be, then a
// Caught update once every input was read and the node composed once, then every change. It ends when ctx ends or an
// input's watch ends.