v2.0.0: claims model - signed MMUR2 votes in a truth DB, merged view in a rebuildable cache DB; POST /api/claims, claims and merge routes, unsigned writes answer 410
Build and Push Docker Image / build (push) Successful in 5m1s

This commit is contained in:
Worph
2026-10-25 17:36:00 +00:00
parent b0adefb97b
commit 84af298792
78 changed files with 7203 additions and 5617 deletions
+47 -90
View File
@@ -1,109 +1,66 @@
package storage
import (
"context"
"fmt"
"path/filepath"
"sync"
"sync/atomic"
"testing"
"github.com/metazla/meta-core/internal/claim"
)
// BenchmarkConcurrentRecordWrites is the ingest shape the single-writer model
// has to absorb: many goroutines (feeder flushes, gateway persists, plugin
// callbacks) each writing a ~40-field record. SQLite serialises them; this
// measures what that costs. Reported as records/s.
func BenchmarkConcurrentRecordWrites(b *testing.B) {
c := NewClient()
if err := c.Connect(filepath.Join(b.TempDir(), "bench.db")); err != nil {
b.Fatal(err)
// benchRecord is a 40-field signed record, the shape gateway hits persist.
func benchRecord(b *testing.B, c *Client, i int) []claim.Claim {
t := &testing.T{}
id := signer(t, byte(1+i%7))
cid := fmt.Sprintf("bafkbench%012d", i)
out := make([]claim.Claim, 0, 40)
for f := 0; f < 40; f++ {
out = append(out, vote(t, id, cid, fmt.Sprintf("field%02d", f), fmt.Sprintf("value-%d-%d", i, f), 1000))
}
defer c.Close()
record := func(i int64) map[string]string {
m := map[string]string{
"title": fmt.Sprintf("Some Show S01E%02d", i%40),
"fileName": fmt.Sprintf("some.show.s01e%02d.1080p.mkv", i%40),
"filePath": fmt.Sprintf("/files/watch/some.show.%d.mkv", i),
"fileType": "video",
"tmdbid": fmt.Sprintf("%d", 1000+i%500),
fmt.Sprintf("cids/bafkbench%020d", i): "true",
}
for f := 0; len(m) < 40; f++ {
m[fmt.Sprintf("categories/%d", f)] = "true"
}
return m
}
const writers = 16
var next int64
b.ResetTimer()
var wg sync.WaitGroup
for w := 0; w < writers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
i := atomic.AddInt64(&next, 1)
if i > int64(b.N) {
return
}
if err := c.SetMetadataFlat(fmt.Sprintf("01BENCH%019d", i), record(i)); err != nil {
b.Error(err)
return
}
}
}()
}
wg.Wait()
b.ReportMetric(float64(b.N)/b.Elapsed().Seconds(), "records/s")
return out
}
// BenchmarkConcurrentRepersistUnchanged is the dominant write on a permanent
// store: a gateway re-persisting hits it already holds. The kv layer skips
// every unchanged field, so this should cost reads only.
func BenchmarkConcurrentRepersistUnchanged(b *testing.B) {
c := NewClient()
if err := c.Connect(filepath.Join(b.TempDir(), "bench.db")); err != nil {
b.Fatal(err)
}
// BenchmarkConcurrentClaimWrites measures new 40-claim records, 16 writers.
func BenchmarkConcurrentClaimWrites(b *testing.B) {
c := openClient(&testing.T{}, b.TempDir())
defer c.Close()
const distinct = 2000
rec := func(i int64) map[string]string {
m := map[string]string{
"title": fmt.Sprintf("Some Show S01E%02d", i%40),
"fileType": "video",
fmt.Sprintf("cids/bafkbench%020d", i): "true",
}
for f := 0; len(m) < 40; f++ {
m[fmt.Sprintf("categories/%d", f)] = "true"
}
return m
recs := make([][]claim.Claim, b.N)
for i := range recs {
recs[i] = benchRecord(b, c, i)
}
for i := int64(0); i < distinct; i++ {
if err := c.SetMetadataFlat(fmt.Sprintf("01BENCH%019d", i), rec(i)); err != nil {
b.ResetTimer()
b.SetParallelism(16)
var next int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
i := int(atomicAdd(&next) - 1)
if _, err := c.WriteClaims(context.Background(), recs[i]); err != nil {
b.Error(err)
}
}
})
}
// BenchmarkRepersistUnchangedClaims measures the 94% case: the same signed
// claims again (skip-identical before verification).
func BenchmarkRepersistUnchangedClaims(b *testing.B) {
c := openClient(&testing.T{}, b.TempDir())
defer c.Close()
const distinct = 200
recs := make([][]claim.Claim, distinct)
for i := range recs {
recs[i] = benchRecord(b, c, i)
if _, err := c.WriteClaims(context.Background(), recs[i]); err != nil {
b.Fatal(err)
}
}
const writers = 16
var next int64
b.ResetTimer()
var wg sync.WaitGroup
for w := 0; w < writers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
i := atomic.AddInt64(&next, 1)
if i > int64(b.N) {
return
}
if err := c.SetMetadataFlat(fmt.Sprintf("01BENCH%019d", i%distinct), rec(i%distinct)); err != nil {
b.Error(err)
return
}
}
}()
for i := 0; i < b.N; i++ {
if _, err := c.WriteClaims(context.Background(), recs[i%distinct]); err != nil {
b.Fatal(err)
}
}
wg.Wait()
b.ReportMetric(float64(b.N)/b.Elapsed().Seconds(), "records/s")
}
func atomicAdd(p *int64) int64 { return atomic.AddInt64(p, 1) }