A-112: the node-engine reads recovery-wait-minutes from a file its manifest declares, 90 when missing
The manifest declares the file recovery-wait (content ${config:recovery-wait-minutes}); the node-engine reads it at its start and
does not call stdio.Config, which needs the runtime that launches a bundle.
Builds: design 47 G §633, A-112
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -3,10 +3,12 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/meshrecovery"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
|
||||
"github.com/novox/mesh-host/internal/agent"
|
||||
"github.com/novox/mesh-host/internal/link"
|
||||
@@ -68,15 +70,19 @@ func recoveryEnv(session *link.Session, composer *selfcompose.Composer) *agent.R
|
||||
}
|
||||
}
|
||||
|
||||
// recoveryWaitMinutes is the manifest's config key recovery-wait-minutes, read through mesh-sdk's stdio.Config; its default is
|
||||
// the design's 90 (design 47 G §633).
|
||||
// recoveryWaitFile is the file the manifest declares with the content ${config:recovery-wait-minutes} (design 47 G §633, A-112): the
|
||||
// node-engine is no bundle under a runtime, so it reads the setting from its file at its start, as the builder does (A-71).
|
||||
var recoveryWaitFile = "/var/lib/mesh-host/recovery-wait-minutes"
|
||||
|
||||
// recoveryWaitMinutes is the bound of the wait for the recovery module, in minutes: the file's number, the design's 90 when the
|
||||
// file is missing, empty or not a positive number (design 47 G §554, A-112).
|
||||
func recoveryWaitMinutes() int {
|
||||
raw, err := stdio.Config("recovery-wait-minutes")
|
||||
raw, err := os.ReadFile(recoveryWaitFile)
|
||||
if err != nil {
|
||||
return agent.RecoveryWaitMinutes
|
||||
}
|
||||
var n int
|
||||
if json.Unmarshal(raw, &n) != nil || n <= 0 {
|
||||
n, err := strconv.Atoi(strings.TrimSpace(string(raw)))
|
||||
if err != nil || n <= 0 {
|
||||
return agent.RecoveryWaitMinutes
|
||||
}
|
||||
return n
|
||||
|
||||
@@ -5,6 +5,8 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -78,6 +80,21 @@ func TestNatsTheRecoveryStepAsksHearsBoundsAndCatchesUpOverTheBus(t *testing.T)
|
||||
}
|
||||
t.Cleanup(func() { _ = toolSub.Unsubscribe() })
|
||||
|
||||
// A-112: the bound is the number in the file the manifest declares, 90 where it is missing or not a number.
|
||||
for content, want := range map[string]int{"45\n": 45, "": 90, "soon\n": 90, "0\n": 90} {
|
||||
recoveryWaitFile = filepath.Join(t.TempDir(), "w")
|
||||
if err := os.WriteFile(recoveryWaitFile, []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := recoveryWaitMinutes(); got != want {
|
||||
t.Errorf("the file %q gives %d minutes, want %d", content, got, want)
|
||||
}
|
||||
}
|
||||
recoveryWaitFile = filepath.Join(t.TempDir(), "missing")
|
||||
if got := recoveryWaitMinutes(); got != 90 {
|
||||
t.Errorf("no file gives %d minutes, want 90", got)
|
||||
}
|
||||
|
||||
say("old", meshrecovery.RestoredEventOutcomeFailed) // said before anyone listens: the last message of the subject
|
||||
session := b.startSession()
|
||||
r := recoveryEnv(session, nil)
|
||||
|
||||
@@ -105,6 +105,13 @@
|
||||
"path": "/var/lib/mesh-host/operator-keys",
|
||||
"mode": "0644",
|
||||
"content": "${config:operator-signers}\n"
|
||||
},
|
||||
{
|
||||
"id": "recovery-wait",
|
||||
"type": "file",
|
||||
"path": "/var/lib/mesh-host/recovery-wait-minutes",
|
||||
"mode": "0644",
|
||||
"content": "${config:recovery-wait-minutes}\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -76,6 +76,9 @@ func TestTheManifestConsumesTheBackupEvent(t *testing.T) {
|
||||
t.Errorf("invokes %v lacks %s", m.Invokes, v)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(string(raw), `"content": "${config:recovery-wait-minutes}\n"`) {
|
||||
t.Errorf("module.json declares no file with the content ${config:recovery-wait-minutes} (design 47 G A-112)")
|
||||
}
|
||||
if m.Config["recovery-wait-minutes"].Default != float64(90) {
|
||||
t.Errorf("config recovery-wait-minutes is %+v, want default 90", m.Config["recovery-wait-minutes"])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user