Files
mesh-catalog/modules/nats/internal/keeper/fill.go
T
jschoubben cc1a942235 CAT-N6: the fill pass raises full at the raise mark and clears it below the clear mark; the keeper's health
The keeper's one periodic read (ADR 0595 §6): every entry that refuses when
full, by its fullest object; full raised at the raise mark (75 by default),
cleared only below the clear mark (70), so an entry at the mark does not flap;
an entry dropping its oldest is never read. HealthOf is the keeper's health
for its tool: unhealthy when its pass is more than three minutes old, its
first view has not answered (naming the indexer's verb), or verdicts wait on
its consumer unanswered past the bound; it names the entries refused, waiting
and full beside.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 12:34:59 +01:00

73 lines
2.1 KiB
Go

package keeper
import (
"context"
"fmt"
"time"
"git.novox.be/novox/mesh-sdk/go/asks"
)
// FillPass reads the fill of every entry that refuses when full (ADR 0595 §6), raising `full` at the raise mark and
// clearing it only below the clear mark, so an entry at the mark does not flap. It is the keeper's one periodic read.
func (k *Keeper) FillPass() {
raise, clear := k.marks()
keys, err := k.Store.Keys(StateAsked)
if err != nil {
k.logf("the fill pass cannot read its own %s: %v", StateAsked, err)
return
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
for _, module := range keys {
held, _, found := k.asked(module)
if !found {
continue
}
changed := false
for _, local := range sortedKeys(held.Made) {
m := held.Made[local]
if !m.Created {
continue
}
var most int64 = -1
for _, o := range m.Plan.Objects {
if !o.Settings.Refuses() || o.Settings.MaxBytes <= 0 {
continue
}
_, f, there, err := k.Bus.Held(ctx, o)
if err != nil || !there {
continue
}
if p := int64(f.Bytes) * 100 / o.Settings.MaxBytes; p > most {
most = p
}
}
if most < 0 {
continue
}
was := m
m.Fill = most
switch {
case !m.Full && most >= raise:
m.Full = true
k.emit(EventFull, m.Plan, held.Revision, fmt.Sprintf("%d%% of its cap, past the raise mark %d%%", most, raise), nil, nil)
k.raise(conditionFull, module, local, asks.SeverityWarning, "Kept data is filling up",
"a larger cap in the module's manifest, or data removed",
fmt.Sprintf("%s of %s holds %d%% of its cap and refuses new data when full; it is cleared below %d%%", local, module, most, clear))
case m.Full && most < clear:
m.Full = false
k.emit(EventFullCleared, m.Plan, held.Revision, fmt.Sprintf("%d%% of its cap, below the clear mark %d%%", most, clear), nil, nil)
k.clear(conditionFull, module, local)
}
if m.Fill != was.Fill || m.Full != was.Full {
held.Made[local], changed = m, true
}
}
if changed {
k.write(held)
}
}
k.setStatus(func(s *Status) { s.Pass = k.now() })
}