Files
weichenandCursor be0c1e843f feat(dataset): registry, pause/resume backfill, destroy gates, eight tracks
批准 dataset 分类入库;SKIP LOCKED 分批;销毁默认 fail closed。restore 演练拒绝共享 env DSN。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 02:40:12 +00:00

249 lines
6.5 KiB
Go

package dataset_test
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/url"
"os"
"sync"
"testing"
"time"
"chat-agent-system/internal/artifactvault"
"chat-agent-system/internal/dataset"
"chat-agent-system/internal/db"
"github.com/jackc/pgx/v5/pgxpool"
)
func init() {
if _, err := os.Stat("deploy/postgres/goose"); err == nil {
return
}
for _, cand := range []string{"../..", "../../.."} {
if fi, err := os.Stat(cand + "/deploy/postgres/goose"); err == nil && fi.IsDir() {
_ = os.Chdir(cand)
return
}
}
}
func rewriteDatabaseName(dsn, name string) string {
if u, err := url.Parse(dsn); err == nil && u.Scheme != "" {
u.Path = "/" + name
return u.String()
}
return dsn
}
var (
isoOnce sync.Once
isoPoolA, isoPoolB *pgxpool.Pool
isoErr error
isoCleanup func()
)
func TestMain(m *testing.M) {
code := m.Run()
if isoCleanup != nil {
isoCleanup()
}
os.Exit(code)
}
func openIsolatedU9(t *testing.T) (*pgxpool.Pool, *pgxpool.Pool) {
t.Helper()
if testing.Short() {
t.Skip("U9 PG races are not part of -short")
}
dsn := db.SkipIfNoTestDatabaseURL(t)
db.RefuseSharedEnvDSN(t, dsn)
isoOnce.Do(func() {
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
defer cancel()
adminDSN := rewriteDatabaseName(dsn, "postgres")
admin, err := pgxpool.New(ctx, adminDSN)
if err != nil {
isoErr = err
return
}
const isolated = "agent_rel_m3_u9"
_, _ = admin.Exec(ctx, `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname=$1 AND pid <> pg_backend_pid()`, isolated)
_, _ = admin.Exec(ctx, `DROP DATABASE IF EXISTS `+isolated)
if _, err := admin.Exec(ctx, `CREATE DATABASE `+isolated); err != nil {
admin.Close()
isoErr = err
return
}
isoDSN := rewriteDatabaseName(dsn, isolated)
poolA, err := pgxpool.New(ctx, isoDSN)
if err != nil {
admin.Close()
isoErr = err
return
}
if err := db.RunMigrations(ctx, poolA, db.ResolveMigrationsDir()); err != nil {
poolA.Close()
admin.Close()
isoErr = err
return
}
poolB, err := pgxpool.New(ctx, isoDSN)
if err != nil {
poolA.Close()
admin.Close()
isoErr = err
return
}
isoPoolA, isoPoolB = poolA, poolB
isoCleanup = func() {
poolA.Close()
poolB.Close()
_, _ = admin.Exec(context.Background(), `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname=$1 AND pid <> pg_backend_pid()`, isolated)
_, _ = admin.Exec(context.Background(), `DROP DATABASE IF EXISTS `+isolated)
admin.Close()
}
})
if isoErr != nil {
t.Fatalf("isolated db: %v", isoErr)
}
return isoPoolA, isoPoolB
}
func shaBody(s string) (string, string) {
sum := sha256.Sum256([]byte(s))
return hex.EncodeToString(sum[:]), s
}
func seedCommit(t *testing.T, pool *pgxpool.Pool, docID, body string) {
t.Helper()
ctx := context.Background()
sha, md := shaBody(body)
if _, err := pool.Exec(ctx, `
INSERT INTO document_content_blobs (content_sha256, content_markdown, byte_size)
VALUES ($1,$2,$3) ON CONFLICT DO NOTHING
`, sha, md, len(md)); err != nil {
t.Fatal(err)
}
var snapID, verID int64
if err := pool.QueryRow(ctx, `
INSERT INTO document_snapshots (doc_id, content_sha256, source_kind)
VALUES ($1,$2,'agent') RETURNING id
`, docID, sha).Scan(&snapID); err != nil {
t.Fatal(err)
}
if err := pool.QueryRow(ctx, `
INSERT INTO document_versions (doc_id, version_no, status, origin_kind, baseline_snapshot_id, head_snapshot_id)
VALUES ($1,1,'sealed','agent',$2,$2) RETURNING id
`, docID, snapID).Scan(&verID); err != nil {
t.Fatal(err)
}
if _, err := pool.Exec(ctx, `
INSERT INTO document_change_events (
doc_id, version_id, event_no, to_snapshot_id, change_kind, actor_kind, idempotency_key
) VALUES ($1,$2,1,$3,'agent_commit','agent',$4)
`, docID, verID, snapID, "u9:"+docID); err != nil {
t.Fatal(err)
}
}
func TestPG_DuplicateEnqueueAndSkipLocked(t *testing.T) {
poolA, poolB := openIsolatedU9(t)
ctx := context.Background()
seedCommit(t, poolA, "doc_u9_commit", "# u9 agent commit body")
job := dataset.NewJob("u9-race", "dev", "scratch-u9", 38)
pgA := &dataset.PG{Pool: poolA, Env: "dev"}
pgB := &dataset.PG{Pool: poolB, Env: "dev"}
if err := pgA.EnsureJob(ctx, job); err != nil {
t.Fatal(err)
}
n1, err := pgA.EnqueueKind(ctx, job, artifactvault.KindAgentCommit, 0)
if err != nil {
t.Fatal(err)
}
n2, err := pgA.EnqueueKind(ctx, job, artifactvault.KindAgentCommit, 0)
if err != nil {
t.Fatal(err)
}
if n1 < 1 {
t.Fatalf("expected seeded commit, enqueued %d", n1)
}
pending, err := pgA.CountQueue(ctx, job.ID, "pending")
if err != nil {
t.Fatal(err)
}
if pending != n1 {
t.Fatalf("duplicate enqueue grew queue pending=%d first=%d second=%d", pending, n1, n2)
}
var wg sync.WaitGroup
errCh := make(chan error, 2)
for _, pg := range []*dataset.PG{pgA, pgB} {
wg.Add(1)
go func(p *dataset.PG) {
defer wg.Done()
_, err := p.ClaimAndProcess(ctx, job, 50)
errCh <- err
}(pg)
}
wg.Wait()
close(errCh)
for err := range errCh {
if err != nil {
t.Fatal(err)
}
}
arts, err := pgA.CountArtifacts(ctx)
if err != nil {
t.Fatal(err)
}
if arts != 1 {
t.Fatalf("want 1 artifact after two workers, got %d", arts)
}
st, err := pgA.RecalcJob(ctx, job.ID)
if err != nil {
t.Fatal(err)
}
if st.Succeeded != 1 {
t.Fatalf("recalc succeeded=%d scanned=%d", st.Succeeded, st.Scanned)
}
}
func TestPG_PauseStatusAndRegistryImport(t *testing.T) {
poolA, _ := openIsolatedU9(t)
ctx := context.Background()
pg := &dataset.PG{Pool: poolA, Env: "dev"}
job := dataset.NewJob("u9-pause", "dev", "scratch-u9", 38)
if err := pg.EnsureJob(ctx, job); err != nil {
t.Fatal(err)
}
if err := pg.SetJobStatus(ctx, job.ID, dataset.JobPaused); err != nil {
t.Fatal(err)
}
var status string
if err := poolA.QueryRow(ctx, `SELECT status FROM dataset_backfill_jobs WHERE job_id=$1`, job.ID).Scan(&status); err != nil {
t.Fatal(err)
}
if status != dataset.JobPaused {
t.Fatalf("status=%s", status)
}
for i, d := range []dataset.Dataset{
{ID: "pinned-clean", Class: dataset.ClassPinned, DisplayName: "a", StorageIdentity: "scratch-u9", Status: "approved"},
{ID: "demo-minimal", Class: dataset.ClassDemo, DisplayName: "b", StorageIdentity: "scratch-u9", Status: "approved"},
} {
d.SourceSchema = 38
d.SourceCommit = fmt.Sprintf("c%d", i)
if err := pg.UpsertDataset(ctx, d); err != nil {
t.Fatal(err)
}
}
var n int
if err := poolA.QueryRow(ctx, `SELECT COUNT(*) FROM dataset_registry`).Scan(&n); err != nil || n < 2 {
t.Fatalf("registry count=%d err=%v", n, err)
}
}