81 lines
3.0 KiB
Go
81 lines
3.0 KiB
Go
package nodeengineclient
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
seat "git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
|
"git.novox.be/novox/mesh-sdk/go/keys"
|
|
)
|
|
|
|
// A node's own health report (the state health, one key per node, written by that node's engine alone) and the data items
|
|
// a module declares as the engine placed them (the state data, `<node>.<module>`): their layouts are the seat's contract
|
|
// (seat.HealthByNodeValue, seat.DataByNodeModuleValue); this file is their codec, shared by the engine and its readers.
|
|
|
|
// EncodeHealth is h as JSON at the current version; it refuses a report naming no node, and a fall back to the old login
|
|
// that names another node, no login fallen back from, no reason or no time.
|
|
func EncodeHealth(h seat.HealthByNodeValue) ([]byte, error) {
|
|
h.V = keys.Version
|
|
if h.Node == "" {
|
|
return nil, fmt.Errorf("node-engine: a node's health report names its node")
|
|
}
|
|
if f := h.Fallback; f != nil && (f.Node != h.Node || f.From == "" || f.Why == "" || f.At.IsZero()) {
|
|
return nil, fmt.Errorf("node-engine: a node's fall back to its old login names its node %s, the login fallen back from, why and when", h.Node)
|
|
}
|
|
return json.Marshal(h)
|
|
}
|
|
|
|
// DecodeHealth reads a report; it refuses another version (keys.ErrUnknownVersion) and a field the contract does not know.
|
|
func DecodeHealth(raw []byte) (seat.HealthByNodeValue, error) {
|
|
if err := keys.CheckVersion(raw); err != nil {
|
|
return seat.HealthByNodeValue{}, err
|
|
}
|
|
h, err := seat.DecodeHealthByNodeValue(raw)
|
|
if err != nil {
|
|
return seat.HealthByNodeValue{}, fmt.Errorf("node-engine: a node's health report is not readable: %w", err)
|
|
}
|
|
return h, nil
|
|
}
|
|
|
|
// SameHealth says two reports say the same, whenever each was written.
|
|
func SameHealth(a, b seat.HealthByNodeValue) bool {
|
|
a.At, b.At = time.Time{}, time.Time{}
|
|
return sameJSON(a, b)
|
|
}
|
|
|
|
// DataKey is a module's key on a node in the state data, `<node>.<module>`, its module part escaped as a have's is.
|
|
func DataKey(node, module string) (string, error) { return HaveKey(node, module) }
|
|
|
|
// DataNodeKeys is the pattern of every data key of a node, `<node>.*`.
|
|
func DataNodeKeys(node string) (string, error) {
|
|
if err := keys.CheckName("node", node); err != nil {
|
|
return "", err
|
|
}
|
|
return node + ".*", nil
|
|
}
|
|
|
|
// EncodeData is d as JSON at the current version; it refuses a node or module the key refuses.
|
|
func EncodeData(d seat.DataByNodeModuleValue) ([]byte, error) {
|
|
d.V = keys.Version
|
|
if _, err := DataKey(d.Node, d.Module); err != nil {
|
|
return nil, err
|
|
}
|
|
if d.Items == nil {
|
|
d.Items = []seat.PlacedDataItem{}
|
|
}
|
|
return json.Marshal(d)
|
|
}
|
|
|
|
// DecodeData reads a module's data items; it refuses another version (keys.ErrUnknownVersion).
|
|
func DecodeData(raw []byte) (seat.DataByNodeModuleValue, error) {
|
|
if err := keys.CheckVersion(raw); err != nil {
|
|
return seat.DataByNodeModuleValue{}, err
|
|
}
|
|
d, err := seat.DecodeDataByNodeModuleValue(raw)
|
|
if err != nil {
|
|
return seat.DataByNodeModuleValue{}, fmt.Errorf("node-engine: a module's data items are not readable: %w", err)
|
|
}
|
|
return d, nil
|
|
}
|