Judge each read for its reader with mesh-sdk's ReadsAnnouncedBy, so the parts named for the lease are granted it, and say a refusal once (issue 774)
2536 reads of mesh-controller.lease were refused on 2026-10-30 (mesh-vault, mesh-grants, the assigner, artifact-store-tools, the watchman, mesh-config). The controller composed the bus's users with its own copy of a reader-less judgement (internal/broker ReadsAnnounced), which knows no named readers: the lease is announced readable by nobody and read by the parts named for it (ADR 0547 clause 9, ADR 0561 §3). The copy is deleted; BusRecords judges each read for its module with buscompose.ReadsAnnouncedBy. Each refusal was also printed on every composition, about 420 times a read; it is now said once per process. mesh-config's read of the lease stays refused: it reads the lease for its take-over (hand-back ends at the lease write, ADR 0561 §3) and is not among the named readers. That is mesh-sdk's NamedReaders, routed to the lead. Quick fix: mark the lease readable in the controller's announcement (tried and reverted: it would open the lease to every module and contradict ADR 0561 §3). Thorough fix: one judgement, the SDK's, for every composer. Chose thorough. Research 072 piece: 03-domains, mesh-grants (bus membership and grants leave the controller): the controller composes reads with the same SDK function the grants part uses.
This commit is contained in:
@@ -6,7 +6,9 @@ import (
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/buscompose"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"github.com/novox/mesh-controller/internal/broker"
|
||||
)
|
||||
@@ -119,22 +121,18 @@ func (i *Inventory) BusRecords(ctx context.Context) (broker.Records, error) {
|
||||
// announcement does not make readable is granted nothing, and said; an owner that announced nothing yet is read as
|
||||
// before. Announcements that cannot be read are said, and every read is granted as before: the bus's users are
|
||||
// composed either way.
|
||||
//
|
||||
// **Judged for its reader, by the SDK's judgement** (sweep 2026-10-30, issue 774): mesh-sdk buscompose's
|
||||
// ReadsAnnouncedBy knows the named readers (ADR 0547 clause 9, ADR 0561 §3), so the lease is granted to the parts
|
||||
// named for it and refused to every other. The controller's own reader-less copy refused every named reader: 2536
|
||||
// refused reads of mesh-controller.lease on 2026-10-30, each said on every composition.
|
||||
if Announcements != nil {
|
||||
announced, err := Announcements(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("the states the modules announced cannot be read, so every read is granted from `reads` as before: %v\n", err)
|
||||
} else {
|
||||
out.Announced = announced
|
||||
for node, ds := range out.Assigned {
|
||||
for k := range ds {
|
||||
granted, refused := broker.ReadsAnnounced(ds[k].Reads, announced)
|
||||
ds[k].Reads, ds[k].ReadsRefused = granted, refused
|
||||
for _, r := range refused {
|
||||
fmt.Printf("%s on %s reads %s, which its owner does not announce readable: not granted\n",
|
||||
ds[k].Module, node, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
judgeReads(out.Assigned, announced, sayRefusedOnce)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,3 +613,29 @@ func hearsOf(m catalogue.Manifest, declared map[string]catalogue.Manifest, node
|
||||
}
|
||||
return out, touches, onEvents
|
||||
}
|
||||
|
||||
// refusalsSaid are the refused reads already said by this process, by `<module>@<node> <read>`: a refusal is said once,
|
||||
// when first composed, not on every composition (about 420 times a read on 2026-10-30). `status` names them all.
|
||||
var refusalsSaid sync.Map
|
||||
|
||||
// sayRefusedOnce says a refused read the first time this process composes it.
|
||||
func sayRefusedOnce(module, node, read string) {
|
||||
if _, said := refusalsSaid.LoadOrStore(module+"@"+node+" "+read, true); said {
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s on %s reads %s, which its owner does not make readable by it: not granted\n", module, node, read)
|
||||
}
|
||||
|
||||
// judgeReads splits each assigned module's reads into granted and refused, for that module, by what the owners announced
|
||||
// and the states' named readers (buscompose.ReadsAnnouncedBy), and says each refusal.
|
||||
func judgeReads(assigned map[string][]broker.Declared, announced map[string]announce.States, say func(module, node, read string)) {
|
||||
for node, ds := range assigned {
|
||||
for k := range ds {
|
||||
granted, refused := buscompose.ReadsAnnouncedBy(ds[k].Module, ds[k].Reads, announced)
|
||||
ds[k].Reads, ds[k].ReadsRefused = granted, refused
|
||||
for _, r := range refused {
|
||||
say(ds[k].Module, node, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"github.com/novox/mesh-controller/internal/broker"
|
||||
)
|
||||
|
||||
// Sweep 2026-10-30 (issue 774): a read is judged for its reader. The controller's lease, which its announcement marks
|
||||
// readable by nobody, is granted to the parts named for it (ADR 0561 §3) and refused to every other; a state its owner
|
||||
// announced readable is granted; one it keeps and did not is refused; an owner that announced nothing is read as before.
|
||||
// Each refusal is said, and a refusal already said is not said again.
|
||||
func TestAReadIsJudgedForItsReader(t *testing.T) {
|
||||
announced := map[string]announce.States{
|
||||
"mesh-controller": broker.ControllerAnnouncement("novox"),
|
||||
"owner": {Module: "owner", States: []announce.State{{Name: "open", Readable: true}, {Name: "closed"}}},
|
||||
}
|
||||
for name, c := range map[string]struct {
|
||||
reader, read string
|
||||
granted bool
|
||||
}{
|
||||
"the lease, by the vault": {"mesh-vault", "mesh-controller.lease", true},
|
||||
"the lease, by the grants part": {"mesh-grants", "mesh-controller.lease", true},
|
||||
"the lease, by a module not named": {"mesh-config", "mesh-controller.lease", false},
|
||||
"a readable state": {"reader", "owner.open", true},
|
||||
"a state kept and not readable": {"reader", "owner.closed", false},
|
||||
"an owner that announced nothing": {"reader", "quiet.any", true},
|
||||
"a mirror the controller marks open": {"pacman", "mesh-controller.declared-packages", true},
|
||||
} {
|
||||
assigned := map[string][]broker.Declared{"novox": {{Module: c.reader, Reads: []string{c.read}}}}
|
||||
var said []string
|
||||
judgeReads(assigned, announced, func(module, node, read string) { said = append(said, read) })
|
||||
d := assigned["novox"][0]
|
||||
if slices.Contains(d.Reads, c.read) != c.granted || slices.Contains(d.ReadsRefused, c.read) == c.granted {
|
||||
t.Errorf("%s: granted %v, refused %v", name, d.Reads, d.ReadsRefused)
|
||||
}
|
||||
if (len(said) == 1) == c.granted {
|
||||
t.Errorf("%s: said %v", name, said)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user