Declare every module's data; the backup holder measures it (hq ADR 0233)

Backup lines are derived from each module's data section instead of written by hand; the holder
measures declared items, reads the array under them, and deletes a retired item only after a last
restore point; the Go providers say each held consumer's size so an empty replacement is seen.
This commit is contained in:
jochen
2026-10-06 16:47:49 +02:00
parent 8f5a75ab9b
commit 685cb1cb1b
44 changed files with 1493 additions and 78 deletions
@@ -98,7 +98,7 @@ const SetAsideStatement = `SELECT datname, pg_database_size(datname) FROM pg_dat
// Inventory is what this server holds that the mesh made.
func (c *Client) Inventory(ctx context.Context) (Inventory, error) {
inv := Inventory{Active: []string{}, Retired: []Retired{}}
inv := Inventory{Active: []string{}, Retired: []Retired{}, Sizes: map[string]int64{}}
r, err := c.Query(ctx, "", InventoryStatement)
if err != nil {
return inv, err
@@ -111,6 +111,9 @@ func (c *Client) Inventory(ctx context.Context) (Inventory, error) {
}
if login && m.Retired == "" {
inv.Active = append(inv.Active, name)
if s := sizeOf(size); s >= 0 {
inv.Sizes[name] = s
}
continue
}
at, _ := time.Parse(time.RFC3339, m.Retired)
@@ -89,6 +89,9 @@ type Retired struct {
type Inventory struct {
Active []string
Retired []Retired
// Sizes is what each active consumer keeps on the backend, in bytes, where the backend can say: what
// the controller tells an empty replacement of a consumer's data by (novox/hq ADR 0233).
Sizes map[string]int64
}
// retirement is the loop's memory of the sets it is counting, waiting on and was told to keep.
@@ -421,7 +424,13 @@ func (h *Harness) Retirement(ctx context.Context) (map[string]any, error) {
retired = append(retired, map[string]any{"consumer": r.Consumer, "node": r.Node,
"retired_at": stampOr(r.RetiredAt), "why": r.Why, "size_bytes": r.SizeBytes, "kind": kindOf(r)})
}
out := map[string]any{"resource": h.Resource, "node": h.Node, "held": orEmptyList(held),
sizes := map[string]int64{}
for _, as := range held {
if size, ok := inv.Sizes[as]; ok && size >= 0 {
sizes[as] = size
}
}
out := map[string]any{"resource": h.Resource, "node": h.Node, "held": orEmptyList(held), "held_sizes": sizes,
"stable_passes": h.StablePasses, "stable_for_seconds": int(h.StableFor.Seconds()), "bound": h.bound(len(h.applied)), "waiting": nil, "rejected": nil,
"retired": retired}
if w := h.r.waiting; w != nil {