Readings and last good nights are the owners' published packages: disk-load's diskreadings and restic's backupgood, taken by series (B5b Left 3; ADR 0634 §4; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 14:48:10 +01:00
parent c7ae96414f
commit e0eecbf3c8
43 changed files with 565 additions and 147 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ package main
import (
"encoding/json"
"fmt"
"git.novox.be/novox/mesh-sdk/go/health"
"git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings"
"os"
"path/filepath"
"time"
@@ -124,7 +124,7 @@ func (m *Machine) leave(p string, v any) error {
type Asker func(key string, body any) (json.RawMessage, error)
// Readings reads disk-load's readings of one machine's data items (its state `readings`, ADR 0571 clause 3).
type Readings func(node string) ([]health.Reading, error)
type Readings func(node string) ([]diskreadings.Reading, error)
// LeaveData reads disk-load for where the mesh keeps data on this machine and leaves the paths for the
// process (finding 4d). A failed ask keeps the last paths, with why; with none, the process sets up
+2 -2
View File
@@ -8,7 +8,7 @@ package main
import (
"errors"
"fmt"
"git.novox.be/novox/mesh-sdk/go/health"
"git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings"
"io"
"os"
"path/filepath"
@@ -65,7 +65,7 @@ func sortWants(w []Want) {
// PathsFrom is the paths disk-load's readings name: where the mesh keeps data here. No reading is an error, never an
// empty list: an empty list would let every mount point through.
func PathsFrom(readings []health.Reading) ([]string, error) {
func PathsFrom(readings []diskreadings.Reading) ([]string, error) {
if len(readings) == 0 {
return nil, errors.New("disk-load keeps no reading of this machine's data yet")
}
+5 -5
View File
@@ -13,7 +13,7 @@ import (
"context"
"encoding/json"
"fmt"
"git.novox.be/novox/mesh-sdk/go/health"
"git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings"
"os"
"os/signal"
"strings"
@@ -64,13 +64,13 @@ func shareOnTheBus(m *Machine) {
_, err := stdio.State(SharesState).Put(key, value)
return err
}
read := func(node string) ([]health.Reading, error) {
st := stdio.State(health.ReadingsRead)
read := func(node string) ([]diskreadings.Reading, error) {
st := stdio.State(diskreadings.ReadingsRead)
keys, err := st.Keys()
if err != nil {
return nil, err
}
var out []health.Reading
var out []diskreadings.Reading
for _, k := range keys {
if !strings.HasPrefix(k, node+".") {
continue
@@ -82,7 +82,7 @@ func shareOnTheBus(m *Machine) {
if e == nil {
continue
}
if r, err := health.DecodeReading(e.Value); err == nil {
if r, err := diskreadings.DecodeReading(e.Value); err == nil {
out = append(out, r)
}
}
@@ -10,6 +10,7 @@ import (
)
type manifest struct {
Packages map[string]string `json:"packages"`
Tools []string `json:"tools"`
Requires []string `json:"requires"`
Reads []string `json:"reads"`
@@ -46,6 +47,12 @@ func readManifest(t *testing.T) (manifest, string) {
// or acts; the module requires the share, asks the server's seat and holds node-mounts.
func TestTheManifestNamesWhatTheBundleServesAndWhatItNeeds(t *testing.T) {
m, raw := readManifest(t)
// The readings' layouts are the owners' published packages, taken by their series (ADR 0634 §4).
for _, pk := range []string{"diskreadings"} {
if m.Packages[pk] != "0.1" {
t.Errorf("packages %v: want %s of series 0.1", m.Packages, pk)
}
}
var tools, verbs []string
for _, tl := range Tools(newSystem(t).machine()) {
if !strings.HasSuffix(tl.Description, "(r)") && !strings.HasSuffix(tl.Description, "(a)") {
+5 -5
View File
@@ -5,8 +5,8 @@ package main
import (
"context"
"encoding/json"
"git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/health"
"os"
"path/filepath"
"strings"
@@ -200,7 +200,7 @@ func TestWithoutTheMeshsDataNothingNewIsSetUp(t *testing.T) {
func TestTheBundleLeavesTheMeshsDataForTheProcess(t *testing.T) {
f := newSystem(t)
f.write(ConfigFile, libraryOnly)
rs := []health.Reading{{V: 1, Node: "workstation", PlacedDataItem: catalogue.PlacedDataItem{Module: "plex", ID: "data", Path: "/mnt/plex/data"}}}
rs := []diskreadings.Reading{{V: 1, Node: "workstation", PlacedDataItem: catalogue.PlacedDataItem{Module: "plex", ID: "data", Path: "/mnt/plex/data"}}}
paths, err := PathsFrom(rs)
if err != nil || len(paths) != 1 || paths[0] != "/mnt/plex/data" {
t.Fatalf("paths %q %v", paths, err)
@@ -284,13 +284,13 @@ func callVerb(t *testing.T, m *Machine, name string, args map[string]any) (any,
func TestTheBundleKeepsTheLastDataWhenAnAskFails(t *testing.T) {
f := newSystem(t)
m := f.machine()
ok := func(node string) ([]health.Reading, error) {
return []health.Reading{{V: 1, Node: node, PlacedDataItem: catalogue.PlacedDataItem{Module: "plex", ID: "data", Path: "/mnt/plex/data"}}}, nil
ok := func(node string) ([]diskreadings.Reading, error) {
return []diskreadings.Reading{{V: 1, Node: node, PlacedDataItem: catalogue.PlacedDataItem{Module: "plex", ID: "data", Path: "/mnt/plex/data"}}}, nil
}
if said := m.LeaveData("workstation", ok, time.Now()); len(said) != 0 {
t.Fatalf("said %q", said)
}
failing := func(string) ([]health.Reading, error) { return nil, os.ErrDeadlineExceeded }
failing := func(string) ([]diskreadings.Reading, error) { return nil, os.ErrDeadlineExceeded }
said := m.LeaveData("workstation", failing, time.Now())
d, err := readJSON[DataPaths](m, DataFile)
if err != nil || len(d.Paths) != 1 || d.Paths[0] != "/mnt/plex/data" || d.Error == "" || len(said) == 0 {
+4
View File
@@ -13,3 +13,7 @@ require (
golang.org/x/crypto v0.57.0 // indirect
golang.org/x/sys v0.48.0 // indirect
)
require git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings v0.0.0-00010101000000-000000000000
replace git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings => ../disk-load/diskreadings
+3
View File
@@ -1,6 +1,9 @@
{
"module": "mounts",
"version": "1",
"packages": {
"diskreadings": "0.1"
},
"requires": [
"nfs-share"
],