Fill a module again when the node-engine's socket returns after any failed fill, not only one for want of the socket (issue 1873)
mesh/merge-gate head 16331cdfdce6 merged into trunk 66c404fd39a5 — pass: builds mesh-provisioner-client → ace, g14, novox, shanks; no bus step; every machi…
mesh/repo-check head 16331cdfdce6 merged into trunk 66c404fd39a5 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
mesh/check failed: mesh-build-go: no go build node qualifies: builders disagree: go1.27.1-X:nodwarf5 recipe 74744709d277ded9 on g14; go1.27.3-X:nodwar…

On ace postgres's fill of superuser.secret failed at 22:12 with the engine's own
"is a directory", what a container runtime had left at the path. The engine
delivered at 22:42 clears such a directory, but the client tried again only
modules whose fill had failed for want of the socket (issue 1165), so postgres
was never filled again and its old failure was said every 30 s. A newer engine
may write what the older could not: any failed fill is now tried again when a
node-engine makes its socket again.
This commit is contained in:
2026-10-22 22:56:16 +02:00
parent ab3722d3b3
commit 16331cdfdc
@@ -120,7 +120,7 @@ type Client struct {
// Now dates the reports; nil is time.Now.
Now func() time.Time
// SocketUp wakes the client when the node-engine's write socket is made again (watchSocket); nil never does.
// A module whose write failed for want of the socket is filled again then (issue 1165), and nothing else is.
// A module whose write failed is filled again then (issue 1165, issue 1873), and nothing else is.
SocketUp <-chan struct{}
// watchBound watches a provider's bucket of entries for this machine's keys, once per run (consumers.go); set by
@@ -150,7 +150,8 @@ type state struct {
// of the consumers left out of one of its files.
providing map[string]bool
leftOut map[string]string
// unplaced is a module whose last fill failed for want of the node-engine's write socket (issue 1165).
// unplaced is a module whose last fill failed, for want of the node-engine's write socket (issue 1165) or by the
// engine's own refusal (issue 1873): filled again when the socket is made again.
unplaced map[string]bool
// bound is each provider's bucket of entries this client watches, by key: this machine's consumers' entries alone;
// boundReady is a bucket whose current entries are all read, and boundUsers the modules filled from each.
@@ -705,9 +706,10 @@ func (c *Client) reconcile(ctx context.Context, kvs map[string]jetstream.KeyValu
err = errFill(a)
}
if err != nil {
if socketAbsent(err) {
s.unplaced[module] = true
}
// Filled again when a node-engine makes its socket again: one gone (issue 1165), or one that refused for a
// reason of its own, which a newer engine may write (issue 1873: "is a directory", what a container
// runtime left at the path, cleared by the engine that followed).
s.unplaced[module] = true
failed = append(failed, fmt.Sprintf("%s: %v", f.Path, err))
continue
}