The bus keeper reads a bare stream's max-age-days "none" as kept for good (issue 1966, recovery) #635

Merged
mesh-tools merged 1 commits from fix/keeper-age-none into main 2026-11-08 22:53:04 +00:00
2 changed files with 21 additions and 1 deletions
@@ -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),
+16 -1
View File
@@ -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 }