The licence manager follows the nodes' holdings by an event and asks for them with holdings.asked, instead of reading the agent module's state (ADR 0596 §2). The state holdings stays the module's own. Builds: design 39 bus-and-switch §23 Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
38 lines
1.2 KiB
Go
38 lines
1.2 KiB
Go
package main
|
|
|
|
// What this node holds, said (design 39 bus-and-switch §23): kept in this module's own state `holdings` and said as
|
|
// the event `holdings-changed`, the holdings report whole and never a token, at start, whenever it changes, and again
|
|
// when the licence manager says `holdings.asked`.
|
|
|
|
import "encoding/json"
|
|
|
|
// HoldingsChanged is the event that says what a node holds.
|
|
const HoldingsChanged = "holdings-changed"
|
|
|
|
// HoldingsAsked is the licence manager's event asking every node to say what it holds.
|
|
const HoldingsAsked = Manager + ".holdings.asked"
|
|
|
|
// HoldingsSayer keeps and says what this node holds.
|
|
type HoldingsSayer struct {
|
|
Put func(Holdings) error
|
|
Emit func(Holdings) error
|
|
said string
|
|
}
|
|
|
|
// Say keeps and says now when it differs from what was said last, or always when again: true when it said it. A
|
|
// failure says nothing was said, so the next call tries again.
|
|
func (s *HoldingsSayer) Say(now Holdings, again bool) (bool, error) {
|
|
raw, _ := json.Marshal(now)
|
|
if !again && string(raw) == s.said {
|
|
return false, nil
|
|
}
|
|
if err := s.Put(now); err != nil {
|
|
return false, err
|
|
}
|
|
if err := s.Emit(now); err != nil {
|
|
return false, err
|
|
}
|
|
s.said = string(raw)
|
|
return true, nil
|
|
}
|