The controller's declared-packages mirror ended with the controller (issue 1126) and is deleted after group B's delivery, so the verb no longer reads or compares it. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
112 lines
3.7 KiB
Go
112 lines
3.7 KiB
Go
package link
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
"github.com/nats-io/nats.go"
|
|
)
|
|
|
|
// ---- the packages this node's compositions declare, in the bus's own storage (novox/hq ADR 0565 §6) ---------------
|
|
|
|
// PackagesBucket is the node-engine's declared state packages, created by the grants part from the engine's manifest as
|
|
// its states health and data are: one key, the node's name, written by that node's engine alone, read by pacman as
|
|
// mesh-host.packages (delivery.EnginePackagesRead).
|
|
const PackagesBucket = "mesh-host_" + delivery.EnginePackagesState
|
|
|
|
// packagesStore binds PackagesBucket over the link open now: bound, never created.
|
|
func (l *natsLink) packagesStore() (nats.KeyValue, error) {
|
|
kv, err := l.js.KeyValue(PackagesBucket)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("the node-engine's state %s cannot be bound (it is created from the node-engine's "+
|
|
"manifest; written again at the next composition that changes, or by the node seat's packages with write): %w",
|
|
PackagesBucket, err)
|
|
}
|
|
return kv, nil
|
|
}
|
|
|
|
// packagesStore binds PackagesBucket over a link made of a connection the caller holds (OverNATS), as natsLink does.
|
|
func (b OverNATS) packagesStore() (nats.KeyValue, error) {
|
|
kv, err := b.JS.KeyValue(PackagesBucket)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("the node-engine's state %s cannot be bound: %w", PackagesBucket, err)
|
|
}
|
|
return kv, nil
|
|
}
|
|
|
|
// EnginePackages is this node's key of PackagesBucket over whichever link the session has open
|
|
// (selfcompose.PackagesStore); with none open every read and write is refused, and nothing is kept anywhere else.
|
|
type EnginePackages struct{ Session *Session }
|
|
|
|
func (p EnginePackages) kv() (nats.KeyValue, error) {
|
|
p.Session.init()
|
|
p.Session.mu.Lock()
|
|
bus := p.Session.bus
|
|
p.Session.mu.Unlock()
|
|
l, ok := bus.(interface{ packagesStore() (nats.KeyValue, error) })
|
|
if bus == nil || !ok {
|
|
return nil, ErrNoLink
|
|
}
|
|
return l.packagesStore()
|
|
}
|
|
|
|
// Get is the key's value, nil when it has none.
|
|
func (p EnginePackages) Get(_ context.Context, key string) ([]byte, error) {
|
|
kv, err := p.kv()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
e, err := kv.Get(key)
|
|
if errors.Is(err, nats.ErrKeyNotFound) {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return e.Value(), nil
|
|
}
|
|
|
|
// Put writes the key.
|
|
func (p EnginePackages) Put(_ context.Context, key string, value []byte) error {
|
|
kv, err := p.kv()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = kv.Put(key, value)
|
|
return err
|
|
}
|
|
|
|
// PackagesView is the node seat's verb packages' answer (ADR 0565 §6): this node's key of the engine's state packages.
|
|
// The controller's mirror it was once compared with ended with the controller (issue 1126).
|
|
type PackagesView struct {
|
|
Node string `json:"node"`
|
|
// Key is the node's key as the bus holds it (Source); null when the engine has written none.
|
|
Source string `json:"source"`
|
|
Key *delivery.DeclaredPackages `json:"key"`
|
|
KeyError string `json:"key_error,omitempty"`
|
|
// Wrote says, for write, whether the key was written again (false: it already held what the engine composed).
|
|
Wrote *bool `json:"wrote,omitempty"`
|
|
Note string `json:"note,omitempty"`
|
|
}
|
|
|
|
// PackagesAnswer is the verb's answer from the key as read (nil: no key), with its read's error.
|
|
func PackagesAnswer(node string, key []byte, keyErr error) PackagesView {
|
|
v := PackagesView{Node: node, Source: delivery.EnginePackagesRead}
|
|
if keyErr == nil && key != nil {
|
|
var d delivery.DeclaredPackages
|
|
if keyErr = json.Unmarshal(key, &d); keyErr == nil {
|
|
v.Key = &d
|
|
}
|
|
}
|
|
switch {
|
|
case keyErr != nil:
|
|
v.KeyError = keyErr.Error()
|
|
case v.Key == nil:
|
|
v.Note = "the engine has written no key for this node yet"
|
|
}
|
|
return v
|
|
}
|