Node composer: while the seat list is unread the node's own composition is held too, whole, under the scope node; only what runs and the bootstrapped modules go on (ADR 0636 §1; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -1769,10 +1769,14 @@ func mapValues(m map[string]delivery.Composed) []delivery.Composed {
|
||||
// WaitsForTheSeatList is why a module is held while the node has not read the seat list.
|
||||
const WaitsForTheSeatList = "the node has not read the seat list, so it composes nothing new of this module and keeps what runs of it (novox/hq ADR 0636 §1)"
|
||||
|
||||
// WaitsForTheSeatListOwn is why the node's own composition is held: it folds modules and accounts whose seats the node
|
||||
// cannot judge before the list was read, so only the last applied one runs (ADR 0636 §1).
|
||||
const WaitsForTheSeatListOwn = "the node has not read the seat list, so it composes nothing new of itself and keeps what runs (novox/hq ADR 0636 §1)"
|
||||
|
||||
// holdUntilListed takes out of compositions every module's composition that is new (no running composition has its
|
||||
// digest) while the reader may not act on its seats, and names the module in held: it keeps running what it runs, and
|
||||
// the pass after the list was read hands it. The node's own composition and a module whose composition runs already are
|
||||
// left as they are.
|
||||
// the pass after the list was read hands it. The node's own composition is held the same way, whatever it folds, under
|
||||
// the scope agent.NodeModule; a composition that runs already is left as it is.
|
||||
func (c *Composer) holdUntilListed(ctx context.Context, r reader, compositions map[string]delivery.Composed, held map[string]string, running []delivery.Composed) map[string]string {
|
||||
if c.env.SeatList == nil {
|
||||
return held
|
||||
@@ -1784,21 +1788,24 @@ func (c *Composer) holdUntilListed(ctx context.Context, r reader, compositions m
|
||||
}
|
||||
}
|
||||
for key, comp := range compositions {
|
||||
if comp.Module == "" {
|
||||
continue
|
||||
}
|
||||
if dig, err := delivery.ComposedDigestOf(comp); err == nil && ran[comp.Module+"/"+dig] {
|
||||
continue
|
||||
}
|
||||
if c.env.SeatList.MayAct(c.seatsOf(ctx, r, comp.Module)...) {
|
||||
module, why := comp.Module, WaitsForTheSeatList
|
||||
if module == "" { // the node's own: no seat to judge, so while the list is unread it waits whole
|
||||
if c.env.SeatList.MayAct() {
|
||||
continue
|
||||
}
|
||||
module, why = agent.NodeModule, WaitsForTheSeatListOwn
|
||||
} else if c.env.SeatList.MayAct(c.seatsOf(ctx, r, module)...) {
|
||||
continue
|
||||
}
|
||||
delete(compositions, key)
|
||||
if held == nil {
|
||||
held = map[string]string{}
|
||||
}
|
||||
if _, already := held[comp.Module]; !already {
|
||||
held[comp.Module] = WaitsForTheSeatList
|
||||
if _, already := held[module]; !already {
|
||||
held[module] = why
|
||||
}
|
||||
}
|
||||
return held
|
||||
|
||||
@@ -1812,17 +1812,25 @@ func TestAnUnreadSeatListHoldsWhatIsNewAndHandsItAtTheRead(t *testing.T) {
|
||||
t.Errorf("the node handed %s before it read the seat list", k)
|
||||
}
|
||||
}
|
||||
if !handed["n1.node"] {
|
||||
t.Errorf("the node's own composition was held with the module: %v", handed)
|
||||
// The node's own composition folds modules and accounts it cannot judge before the read: held whole (the ruling of
|
||||
// ADR 0636 §1), under the scope agent.NodeModule.
|
||||
mu.Lock()
|
||||
ownWhy := heldBy[agent.NodeModule]
|
||||
mu.Unlock()
|
||||
if ownWhy != WaitsForTheSeatListOwn || handed["n1.node"] {
|
||||
t.Errorf("the node's own composition is held with %q and handed=%v, want %q and not handed: %v", ownWhy, handed["n1.node"], WaitsForTheSeatListOwn, handed)
|
||||
}
|
||||
// The reader reads the list and says so: the module is handed, with no timer.
|
||||
// The reader reads the list and says so: the module and the node's own are handed, with no timer.
|
||||
g.open.Store(true)
|
||||
changed <- struct{}{}
|
||||
for {
|
||||
seen := map[string]bool{}
|
||||
for !(seen["lemurs"] && seen["node"]) {
|
||||
u := next(t, out)
|
||||
if strings.Contains(u.Key, "lemurs") && !u.Deleted {
|
||||
break
|
||||
if u.Deleted {
|
||||
continue
|
||||
}
|
||||
seen["lemurs"] = seen["lemurs"] || strings.Contains(u.Key, "lemurs")
|
||||
seen["node"] = seen["node"] || u.Key == "n1.node"
|
||||
}
|
||||
mu.Lock()
|
||||
still := heldBy["lemurs"]
|
||||
|
||||
Reference in New Issue
Block a user