package storage import ( "time" ) // CountRoots returns the number of metadata roots in the root index — one // range count over idx:roots/, never the list itself. func (c *Client) CountRoots() (int64, error) { s, err := c.kv() if err != nil { return 0, err } ctx, cancel := opCtx() defer cancel() return s.Count(ctx, rootsNS) } // keyCountTTL bounds how stale CountKeys may be. Counting every row is a full // table scan (~a second at millions of keys), and the only reader is a polled // dashboard tile — it needs a number, not a fresh one every few seconds. const keyCountTTL = 60 * time.Second // CountKeys returns the number of rows in the database — every key, not just // records. It is the denominator for "how much of the store is records": the // flat per-field keys (file:{root}/{field}) dominate, which is expected. func (c *Client) CountKeys() (int64, error) { c.keysMu.Lock() defer c.keysMu.Unlock() if !c.keysAt.IsZero() && time.Since(c.keysAt) < keyCountTTL { return c.keysCount, nil } s, err := c.kv() if err != nil { return 0, err } ctx, cancel := opCtx() defer cancel() n, err := s.CountAll(ctx) if err != nil { return 0, err } c.keysCount, c.keysAt = n, time.Now() return n, nil }