46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
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
|
|
}
|