Review round 1 of the registry milestone (design 25 § 12.2, § 12.3, § 12.7): - the fill pass runs from the start, while the first view is asked; - recreate and drop wake on the operator channel's decided on the keeper's durable consumer, never a minute's tick; - a warrant is spent by compare-and-set (acted.<ask id> in requests) before anything is deleted; a second request on it is refused; a request whose ask ended unanswered is ended, said; the ask is raised before the request is handed; - created is marked only once said; an event or a condition the bus did not take is kept, named by the health and said again at the next fill pass with its one id, on the subjects left (the double publish); - the health judges the first view past its bound and never skips an unread consumer backlog; - an unrecordable hand act is said on the request; nats_requests reads what waits, what ended and each warrant spent, and drops a waiting request by hand; a tool waits for its request's end on one watch of requests; - the whole-module test reads the warrant from the router's record under a process connection. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
package keeper
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
occ "git.novox.be/novox/mesh-contracts/go/clients/operatorchannelclient"
|
|
)
|
|
|
|
// 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() {
|
|
// What the bus did not take before is said again first (design 25 § 12.2).
|
|
k.SayUnsaid()
|
|
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, occ.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() })
|
|
}
|