Design 47's last milestones: the keeper, self-check, healers, hand-acts, provisioner, vault, artifact sweep, disk readings, credential forms (issues 774, 1952, 1953, 1954, 1955)
mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
One commit with exactly the tree of the reviewed head35b4509c0a, on main12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/objectlink"
|
||||
)
|
||||
|
||||
@@ -59,11 +60,11 @@ func linkKeyID(bucket string) string {
|
||||
type server struct {
|
||||
configPath, linksDir, receives string
|
||||
now func() time.Time
|
||||
// seats asks the controller for its seats; a test replaces it.
|
||||
seats func() (json.RawMessage, error)
|
||||
// seats reads the placement seat's state of who holds which seat, every key; a test replaces it.
|
||||
seats func() (map[string][]byte, error)
|
||||
|
||||
mu sync.Mutex
|
||||
holders map[string]bool // "<seat>/<node>.<module>"
|
||||
keys map[string][]byte // seat-holders, as read
|
||||
readAt time.Time
|
||||
haveSet bool
|
||||
}
|
||||
@@ -77,8 +78,23 @@ func newServer(config, links, receives string) (*server, error) {
|
||||
return &server{configPath: config, linksDir: links, receives: receives, now: time.Now, seats: askSeats}, nil
|
||||
}
|
||||
|
||||
func askSeats() (json.RawMessage, error) {
|
||||
return stdio.Ask("seat:mesh-controller.seats", map[string]any{})
|
||||
func askSeats() (map[string][]byte, error) {
|
||||
state := stdio.State(delivery.SeatHoldersRead)
|
||||
names, err := state.Keys()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys := map[string][]byte{}
|
||||
for _, k := range names {
|
||||
e, err := state.Get(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if e != nil {
|
||||
keys[k] = e.Value
|
||||
}
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// link answers one ask.
|
||||
@@ -206,7 +222,7 @@ func (s *server) allowed(g grant, node, module, method string) error {
|
||||
if seat, isSeat := strings.CutPrefix(sh.To, "seat:"); isSeat {
|
||||
held, err := s.holds(seat, node, module)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("a share names seat %s and the controller's seats cannot be read to tell whether this caller holds it: %w", seat, err)
|
||||
return false, fmt.Errorf("a share names seat %s and the placement seat's holders cannot be read to tell whether this caller holds it: %w", seat, err)
|
||||
}
|
||||
return held, nil
|
||||
}
|
||||
@@ -249,58 +265,26 @@ func has(list []string, v string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// holds says whether node.module holds the seat, from the controller's seats, read at most once a minute. A read that
|
||||
// failed is not cached: the next ask reads again.
|
||||
// holds says whether node.module holds the seat, from the placement seat's state of who holds which seat (novox/hq ADR
|
||||
// 0571 clause 4), read at most once a minute. A read that failed is not cached: the next ask reads again.
|
||||
func (s *server) holds(seat, node, module string) (bool, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !s.haveSet || s.now().Sub(s.readAt) >= holdersFor {
|
||||
raw, err := s.seats()
|
||||
keys, err := s.seats()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
set, err := holdersIn(raw)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
s.holders, s.readAt, s.haveSet = set, s.now(), true
|
||||
s.keys, s.readAt, s.haveSet = keys, s.now(), true
|
||||
}
|
||||
return s.holders[seat+"/"+node+"."+module], nil
|
||||
}
|
||||
|
||||
// holdersIn reads the controller's `seats` answer (answer.seats[].holders[] of {node, module}, and answer.outside[] of
|
||||
// {Claim, Node, Module}) into "<seat>/<node>.<module>". The answer may arrive wrapped in {"answer": ...}.
|
||||
func holdersIn(raw json.RawMessage) (map[string]bool, error) {
|
||||
var doc struct {
|
||||
Answer json.RawMessage `json:"answer"`
|
||||
Seats []struct {
|
||||
Seat string `json:"seat"`
|
||||
Holders []struct {
|
||||
Node string `json:"node"`
|
||||
Module string `json:"module"`
|
||||
} `json:"holders"`
|
||||
} `json:"seats"`
|
||||
Outside []struct {
|
||||
Claim, Node, Module string
|
||||
} `json:"outside"`
|
||||
holders, err := delivery.HoldersOf(s.keys, seat, node)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := json.Unmarshal(raw, &doc); err != nil {
|
||||
return nil, fmt.Errorf("the controller's seats answer is not JSON: %w", err)
|
||||
}
|
||||
if len(doc.Answer) > 0 && string(doc.Answer) != "null" {
|
||||
return holdersIn(doc.Answer)
|
||||
}
|
||||
if doc.Seats == nil && doc.Outside == nil {
|
||||
return nil, errors.New("the controller's seats answer holds neither seats nor outside claims")
|
||||
}
|
||||
out := map[string]bool{}
|
||||
for _, s := range doc.Seats {
|
||||
for _, h := range s.Holders {
|
||||
out[s.Seat+"/"+h.Node+"."+h.Module] = true
|
||||
for _, h := range holders {
|
||||
if h.Node == node && h.Module == module {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, o := range doc.Outside {
|
||||
out[o.Claim+"/"+o.Node+"."+o.Module] = true
|
||||
}
|
||||
return out, nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user