test(metrics): isolate large summary seed persistence across reopen

Release qualification crashed in historical baseline SQLite ingestion during the workloads-summary seed. Preserve a metrics-only diagnostic for the same 84,000-row batch shape, with row-count and integrity checks before and after reopen, without the HTTP or reflection fixtures. This does not reproduce or fix the unexplained crash.

Validation: ten focused runs on Go 1.26.7 and one on Go 1.26.8 passed; a one-repeat race run passed. The three-repeat race run timed out at 180 seconds during its final integrity check and remains retained evidence. Omitting the final seed batch makes the row-count assertion fail.
Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot] 2026-09-06 15:59:08 +01:00
parent 9ddee2f8f9
commit e566e575ed

View file

@ -0,0 +1,94 @@
package metrics
import (
"fmt"
"path/filepath"
"testing"
"time"
)
// Exercise the ingestion shape from the workloads-summary benchmark without
// its HTTP, reflection or monitor fixtures. A historical benchmark crashed in
// SQLite during the second synchronous seed; this is a diagnostic invariant,
// not a reproducer or a claim that the unexplained crash has been repaired.
func TestStoreLargeSummarySeedSurvivesReopen(t *testing.T) {
cfg := DefaultConfig(t.TempDir())
cfg.DBPath = filepath.Join(filepath.Dir(cfg.DBPath), "summary-seed.db")
cfg.FlushInterval = time.Hour
cfg.WriteBufferSize = 10_000
store, err := NewStore(cfg)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if store != nil {
if err := store.Close(); err != nil {
t.Error(err)
}
}
})
base := time.Now().Add(-4 * time.Hour).UTC().Truncate(time.Second)
for _, group := range []struct {
kind string
count int
}{{"vm", 30}, {"container", 20}, {"dockerContainer", 20}} {
batch := make([]WriteMetric, 0, group.count*5*240)
for r := 0; r < group.count; r++ {
for _, metric := range []string{"cpu", "memory", "disk", "netin", "netout"} {
for p := 0; p < 240; p++ {
batch = append(batch, WriteMetric{
ResourceType: group.kind, ResourceID: fmt.Sprintf("%s-%d", group.kind, r),
MetricType: metric, Value: float64((r + p) % 100),
Timestamp: base.Add(time.Duration(p) * time.Minute), Tier: TierMinute,
})
}
}
}
store.WriteBatchSync(batch)
}
check := func() {
t.Helper()
var count int
if err := store.db.QueryRow("SELECT COUNT(*) FROM metrics WHERE tier = ?", string(TierMinute)).Scan(&count); err != nil {
t.Fatal(err)
}
if count != 84_000 {
t.Fatalf("persisted minute rows = %d, want 84000", count)
}
rows, err := store.db.Query("PRAGMA integrity_check")
if err != nil {
t.Fatal(err)
}
defer rows.Close()
var results int
for rows.Next() {
var result string
if err := rows.Scan(&result); err != nil {
t.Fatal(err)
}
if result != "ok" {
t.Errorf("integrity_check: %s", result)
}
results++
}
if err := rows.Err(); err != nil {
t.Fatal(err)
}
if results != 1 {
t.Fatalf("integrity_check returned %d rows, want one ok", results)
}
}
check()
if err := store.Close(); err != nil {
t.Fatal(err)
}
store = nil
store, err = NewStore(cfg)
if err != nil {
t.Fatal(err)
}
if err := store.WaitForMaintenance(10 * time.Second); err != nil {
t.Fatal(err)
}
check()
}