Files
beacon-server/db/api_store_integration_test.go
T
MrAlders0n 03f66d1ae4 Database pools by workload, plan router, observe-only guards, metrics (rest of #237) (#238)
* feat(db): five pgx pools with fixed session settings and Prometheus tracing

* feat(guards): per-family observe/enforce guards with client slots, deadlines and a shadow budget

* fix(guards): attribute only guard deadlines and classify like the handlers

* feat(db): route API statements by sqlc name; class C always unnamed

* feat(admin): statement statistics by sqlc name; create pg_stat_statements where allowed

* fix(db): skip pg_stat_statements when no schema is creatable

* feat(background): index health against post-rebuild baselines, Postgres activity, job and ingest metrics

* feat: separate API, ingest and maintenance stores; guards on the public API; metrics listener

* fix(db): keep ingest writes waiting, size the ingest pool to the host, tidy

* test(db): give the statements probe a query id of its own
2026-10-19 07:52:51 -04:00

87 lines
2.9 KiB
Go

// Copyright 2026 Beacon Contributors
// SPDX-License-Identifier: AGPL-3.0-or-later
package db
import (
"context"
"testing"
"time"
"github.com/MeshCore-Beacon/beacon-server/db/planpolicy"
"github.com/MeshCore-Beacon/beacon-server/internal/guards"
"github.com/jackc/pgx/v5/pgxpool"
)
// The API store as main builds it runs the known-routes hop pair unnamed on the real router, in
// every layout: neither statement ever becomes a named prepared statement on its API pool.
func TestAPIStoreHopStatementsUnnamedPostgres(t *testing.T) {
dsn := schemaDSN(t)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
for _, layout := range []planpolicy.Layout{planpolicy.CustomAll, planpolicy.Split, planpolicy.Single} {
t.Run(string(layout), func(t *testing.T) {
// One connection per pool, so pg_prepared_statements on the pool sees the session that ran.
pools, err := OpenPools(ctx, dsn, layout, func(_ string, cfg *pgxpool.Config) { cfg.MaxConns = 1 })
if err != nil {
t.Fatal(err)
}
defer pools.Close()
if err := RunMigrations(ctx, pools.Maint); err != nil {
t.Fatal(err)
}
guard := guards.New(guards.Options{Enforce: guards.Families, ForceObserve: layout == planpolicy.Single, Budget: "shadow"})
store := NewAPIStore(pools, layout, guard, time.Hour, time.Hour)
for range 7 {
if _, err := store.ListKnownRoutes(ctx, "", 2, time.Time{}, 0, 50); err != nil {
t.Fatal(err)
}
if _, err := store.ListKnownRoutes(ctx, "YYZ", 2, time.Time{}, 0, 50); err != nil {
t.Fatal(err)
}
}
apiPool := pools.APICustom
if layout == planpolicy.Single {
apiPool = pools.APILegacy
}
named := func(stmt string) int {
t.Helper()
var n int
if err := apiPool.QueryRow(ctx, "SELECT count(*) FROM pg_prepared_statements WHERE statement LIKE $1",
"-- name: "+stmt+" %").Scan(&n); err != nil {
t.Fatal(err)
}
return n
}
for _, stmt := range []string{"ListKnownRoutesGlobalHop", "ListKnownRoutesByIATAHop"} {
if n := named(stmt); n != 0 {
t.Errorf("%s: %d named prepared statements on the API pool, want 0", stmt, n)
}
}
for _, p := range []*pgxpool.Pool{pools.APILegacy, pools.APICustom, pools.APICached} {
if p == nil || p == apiPool {
continue
}
var n int
if err := p.QueryRow(ctx, "SELECT count(*) FROM pg_prepared_statements WHERE statement LIKE '-- name: ListKnownRoutes%'").Scan(&n); err != nil {
t.Fatal(err)
}
if n != 0 {
t.Errorf("%d known-routes statements prepared on another API pool", n)
}
}
// The detector sees a named statement: the same header run directly on the pool is prepared.
if err := apiPool.QueryRow(ctx, "-- name: ListKnownRoutesGlobalHop :many\nSELECT $1::int", 2).Scan(new(int)); err != nil {
t.Fatal(err)
}
if n := named("ListKnownRoutesGlobalHop"); n != 1 {
t.Errorf("control: %d named prepared statements after a direct run, want 1", n)
}
})
}
}