disk-load retires a reading only on its module's key, and measures as soon as its watch catches up (review round 1)
A round no longer retires readings missing from the watched set, which may be empty or partial; a module's readings are retired when its key of mesh-host_data is deleted or names fewer items. A round refused before the watch caught up runs once it has, not an hour later. disk_round reads this machine's key alone, as its grant allows. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
@@ -59,6 +60,19 @@ type Keeper struct {
|
||||
pmu sync.Mutex
|
||||
pending map[string]bool
|
||||
wake chan struct{}
|
||||
|
||||
// unwatched says a round was refused because the watch had not caught up (ErrNotWatchedYet): one runs as soon as
|
||||
// it has (Watched.Follow), not an hour later.
|
||||
unwatched atomic.Bool
|
||||
}
|
||||
|
||||
// RoundIfRefused runs one round now when the last was refused for a watch not caught up, and says whether it did.
|
||||
func (k *Keeper) RoundIfRefused(ctx context.Context) bool {
|
||||
if !k.unwatched.CompareAndSwap(true, false) {
|
||||
return false
|
||||
}
|
||||
_, _, _ = k.Round(ctx, false)
|
||||
return true
|
||||
}
|
||||
|
||||
// SayEvery is how many items a round measures between two lines saying how far it got.
|
||||
@@ -120,6 +134,9 @@ func (k *Keeper) Round(ctx context.Context, walks bool) (written, kept int, err
|
||||
k.Say("a round of measuring the data declared here starts (walks: %v)", walks)
|
||||
items, err := k.Items(ctx)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNotWatchedYet) {
|
||||
k.unwatched.Store(true)
|
||||
}
|
||||
r.Error = err.Error()
|
||||
end()
|
||||
k.Say("the round measured nothing: %v", err)
|
||||
@@ -164,13 +181,8 @@ func (k *Keeper) Round(ctx context.Context, walks bool) (written, kept int, err
|
||||
}
|
||||
}
|
||||
}
|
||||
retired, err := k.retireGone(items)
|
||||
written += retired
|
||||
r.Written = written
|
||||
if err != nil {
|
||||
failed = append(failed, err.Error())
|
||||
r.Failed = append(r.Failed, FailedItem{Item: "the readings no longer declared", Why: err.Error()})
|
||||
}
|
||||
// A round retires nothing: a reading is retired only when its module's key says so (MeasureModule), never because
|
||||
// an item is missing from what the watch holds now, which may be empty or partial.
|
||||
end()
|
||||
k.Say("the round ended: %d of %d items measured, %d readings written, %d unchanged, %d failed", r.Measured, r.Items,
|
||||
written, kept, len(r.Failed))
|
||||
@@ -237,13 +249,13 @@ func (k *Keeper) MeasureModule(ctx context.Context, module string) {
|
||||
k.Say("%s's data items changed and are not measured: %v", module, err)
|
||||
return
|
||||
}
|
||||
n, err := k.retireGone(module, items[module])
|
||||
if err != nil {
|
||||
k.Say("%s's readings of items it no longer declares here are not retired: %v", module, err)
|
||||
} else if n > 0 {
|
||||
k.Say("%s no longer declares %d item(s) here: their readings are retired, measured no more", module, n)
|
||||
}
|
||||
if len(items[module]) == 0 {
|
||||
n, err := k.retireGone(items)
|
||||
if err != nil {
|
||||
k.Say("%s declares no data item here any more, and its readings are not retired: %v", module, err)
|
||||
return
|
||||
}
|
||||
k.Say("%s declares no data item here any more: %d reading(s) retired, measured no more", module, n)
|
||||
return
|
||||
}
|
||||
written, kept := 0, 0
|
||||
@@ -268,19 +280,19 @@ func (k *Keeper) MeasureModule(ctx context.Context, module string) {
|
||||
kept, len(failed), map[bool]string{true: " (" + strings.Join(failed, "; ") + ")", false: ""}[len(failed) > 0])
|
||||
}
|
||||
|
||||
// retireGone marks retired every reading of this node whose item the node no longer declares — its module was unassigned
|
||||
// there, or is no longer pulled in — with when and why, and keeps it: the record of what the module left behind, until a
|
||||
// person deletes it (ADR 0233). It is cleared when the item is declared again (measureOne).
|
||||
func (k *Keeper) retireGone(declared map[string][]catalogue.PlacedDataItem) (int, error) {
|
||||
// retireGone marks retired every reading of this node of module whose item its key of the engine's state data no longer
|
||||
// names — the key was deleted (the module was unassigned there, or is no longer pulled in) or names fewer items — with
|
||||
// when and why, and keeps it: the record of what the module left behind, until a person deletes it (ADR 0233). It is
|
||||
// asked only on a change of that module's key (novox/hq ADR 0577 clause 2), never from a round. It is cleared when the
|
||||
// item is declared again (measureOne).
|
||||
func (k *Keeper) retireGone(module string, declared []catalogue.PlacedDataItem) (int, error) {
|
||||
keys, err := k.Store.Keys()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
declaredNow := map[string]bool{}
|
||||
for module, its := range declared {
|
||||
for _, it := range its {
|
||||
declaredNow[health.ReadingKey(k.Node, module, it.ID)] = true
|
||||
}
|
||||
for _, it := range declared {
|
||||
declaredNow[health.ReadingKey(k.Node, module, it.ID)] = true
|
||||
}
|
||||
now := k.Measurer.Now().UTC()
|
||||
n := 0
|
||||
@@ -293,7 +305,7 @@ func (k *Keeper) retireGone(declared map[string][]catalogue.PlacedDataItem) (int
|
||||
continue
|
||||
}
|
||||
r, err := health.DecodeReading(raw)
|
||||
if err != nil || r.Node != k.Node || !r.RetiredAt.IsZero() {
|
||||
if err != nil || r.Node != k.Node || r.Module != module || !r.RetiredAt.IsZero() {
|
||||
continue
|
||||
}
|
||||
r.RetiredAt = now
|
||||
|
||||
Reference in New Issue
Block a user