v0.5.0-rc1: slice 5 Phase A — storage observe/report + watchdog (read-only, live)
Fill the slice-3 storage_targets stub and add the fast-poll storage watchdog. Read-only this phase; the host-root surface (mounts/SMART/grow/destructive gate) is Phase B. Hub-owned desired manifest is slice 10, so reconcile against it is built-but-unfed. - internal/storage: StorageTarget wire contract, durable_id derivation per type, HostReader seam (procfs/sysfs, root-free), Observer (storage_targets from ListStorage/NodeStorage + host reads, lvmthin thin-pool fill), and the watchdog (third daemon goroutine; debounced out-of-band report on a known target's attach/disconnect transition). - proxmox.Storage: additive parse-only config fields (durable_id sources). - collector StorageObserver seam; Loop.SetTrigger out-of-band report; daemon runs the watchdog as a third goroutine; StorageConfig knobs. - cross-repo golden kept byte-identical with felhom.eu/hub; bidirectional key-set test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -122,6 +122,33 @@ func TestLoop_RunImmediateAndResilientAfterError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoop_OutOfBandTriggerReportsImmediately(t *testing.T) {
|
||||
// The storage watchdog's trigger channel runs an extra report between ticks (the slow
|
||||
// cadence is 1h here, so any report within the window comes from the trigger).
|
||||
var cn, rn int32
|
||||
loop := NewLoop(
|
||||
&fakeCollector{report: &HostReport{}, n: &cn},
|
||||
&fakeReporter{env: &ControlEnvelope{}, n: &rn},
|
||||
time.Hour, quietLogger())
|
||||
trigger := make(chan struct{}, 1)
|
||||
loop.SetTrigger(trigger)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
done := make(chan error, 1)
|
||||
go func() { done <- loop.Run(ctx) }()
|
||||
|
||||
// Immediate report fires first (1 collect). Then fire the trigger → one more report.
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
trigger <- struct{}{}
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
cancel()
|
||||
<-done
|
||||
|
||||
if got := atomic.LoadInt32(&cn); got < 2 {
|
||||
t.Errorf("collect calls = %d, want ≥2 (immediate + out-of-band trigger)", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoop_RunAdoptsSlowerInterval(t *testing.T) {
|
||||
var cn, rn int32
|
||||
loop := NewLoop(
|
||||
|
||||
Reference in New Issue
Block a user