The bus keeper reads a bare stream's max-age-days "none" as kept for good, as the judge accepts it
mesh/delivery merged: source.main moved to novox/mesh-catalog@7fd4ed589806
mesh/check checking bc8cb3b153cf on 7fd4ed589806
mesh/delivery merged: source.main moved to novox/mesh-catalog@7fd4ed589806
mesh/check checking bc8cb3b153cf on 7fd4ed589806
mesh-knowledge's stream reviews says max-age-days "none", which the indexer's judge accepts
(judge/busstate.go noAge), but the keeper refused it ("not a whole number"), so the stream was
never made and the keeper stayed unhealthy (2026-11-08, issue 1966). Quick fix; the thorough one,
one shared reader of the template options in mesh-sdk catalogue for the judge and the keeper, is
noted on issue 1966.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
This commit is contained in:
@@ -216,6 +216,8 @@ func TestEachTemplateIsPlannedUnderTheModulesNames(t *testing.T) {
|
||||
ledger.Types = []catalogue.LedgerType{{Name: "decision", Indexes: []catalogue.LedgerIndex{{Name: "by-topic", On: []string{"topic"}}}}}
|
||||
bare := entry("raw", catalogue.StorageStream, "", nil)
|
||||
bare.Configuration = map[string]json.RawMessage{"when-full": json.RawMessage(`"drop-oldest"`), "max-mib": json.RawMessage("8"), "max-age-days": json.RawMessage("3")}
|
||||
forGood := entry("reviews", catalogue.StorageStream, "", nil)
|
||||
forGood.Configuration = map[string]json.RawMessage{"when-full": json.RawMessage(`"refuse"`), "max-mib": json.RawMessage("512"), "max-age-days": json.RawMessage(`"none"`)}
|
||||
for _, row := range []struct {
|
||||
name string
|
||||
entry catalogue.BusStateEntry
|
||||
@@ -247,6 +249,9 @@ func TestEachTemplateIsPlannedUnderTheModulesNames(t *testing.T) {
|
||||
{name: "bare stream", entry: bare,
|
||||
objects: "stream mesh-knowledge_raw [mesh.bus.mesh-knowledge.raw.>] {8 MiB, age 259200, history 0, old, size 0}",
|
||||
binding: "stream mesh-knowledge_raw on mesh.bus.mesh-knowledge.raw"},
|
||||
{name: "a bare stream kept for good (max-age-days none, as the judge accepts it)", entry: forGood,
|
||||
objects: "stream mesh-knowledge_reviews [mesh.bus.mesh-knowledge.reviews.>] {512 MiB, age 0, history 0, new, size 0}",
|
||||
binding: "stream mesh-knowledge_reviews on mesh.bus.mesh-knowledge.reviews"},
|
||||
{name: "a local name holding the separator", entry: entry("my_drafts", catalogue.StorageKeyValue, catalogue.TemplateState, nil),
|
||||
refused: `the local name "my_drafts" is empty or holds "_"`},
|
||||
{name: "objects with no cap", entry: entry("files", catalogue.StorageObjectStore, catalogue.TemplateObjects, nil),
|
||||
|
||||
@@ -226,7 +226,7 @@ func PlanOf(module string, e catalogue.BusStateEntry) (Plan, error) {
|
||||
if err != nil {
|
||||
return Plan{}, err
|
||||
}
|
||||
age, err := conf.int(catalogue.OptionAgeDays, -1)
|
||||
age, err := conf.ageDays(-1)
|
||||
if err != nil {
|
||||
return Plan{}, err
|
||||
}
|
||||
@@ -283,6 +283,21 @@ func days(n int64) int64 {
|
||||
return int64((time.Duration(n) * 24 * time.Hour) / time.Second)
|
||||
}
|
||||
|
||||
// noAge is how a bare stream says it keeps its messages for good, as the indexer's judge accepts it
|
||||
// (mesh-delivery modules/mesh-delivery-indexer/judge/busstate.go noAge): kept as no age limit.
|
||||
const noAge = "none"
|
||||
|
||||
// ageDays is a bare stream's max-age-days: a whole number of days, or "none" for no limit (0).
|
||||
func (o options) ageDays(fallback int64) (int64, error) {
|
||||
if raw, ok := o.raw[catalogue.OptionAgeDays]; ok {
|
||||
var word string
|
||||
if json.Unmarshal(raw, &word) == nil && word == noAge {
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
return o.int(catalogue.OptionAgeDays, fallback)
|
||||
}
|
||||
|
||||
// options reads a template's options as the manifest wrote them.
|
||||
type options struct{ raw map[string]json.RawMessage }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user