Files
Agent-System/internal/app/docflow/same_tx_pg_test.go
T
weichenandCursor 0f2057765a test(docflow): prove three production chains share one Postgres transaction
Isolated-library coverage checks approved/candidate/impact envelopes, empty-env rollback, and zero FAV staging rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 08:52:48 +00:00

86 lines
2.6 KiB
Go

package docflow_test
import (
"context"
"errors"
"os"
"strings"
"testing"
"time"
"chat-agent-system/internal/app/uow"
"chat-agent-system/internal/artifactvault"
"chat-agent-system/internal/db"
"chat-agent-system/internal/events"
"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 TestOutboxAndStagingSameTxRollback(t *testing.T) {
if testing.Short() {
t.Skip("same-tx outbox/staging is not part of -short")
}
dsn := db.SkipIfNoTestDatabaseURL(t)
if strings.Contains(dsn, "5433") || strings.Contains(dsn, "agent_system_dev") ||
(strings.Contains(dsn, "5434") && strings.Contains(dsn, "agent_system_test")) ||
strings.Contains(dsn, "5435") {
t.Fatal("TEST_DATABASE_URL points at a shared env port; refuse agent_system_dev/test/main")
}
ctx := context.Background()
pool, err := pgxpool.New(ctx, dsn)
if err != nil {
t.Fatal(err)
}
t.Cleanup(pool.Close)
if err := db.RunMigrationsOnceForTest(ctx, pool, dsn); err != nil {
t.Fatalf("migrate: %v", err)
}
body := []byte(`{"doc_id":"doc_m2_tx","version_no":1}`)
env := events.Envelope{
EventID: "document:doc_m2_tx:v1", EventName: "document.agent_version_committed",
SchemaVersion: events.EnvelopeSchema, Environment: "dev", ProjectID: 9,
AggregateType: "document", AggregateID: "doc_m2_tx", AggregateVersion: 1,
ActorRef: "user:1", IdempotencyKey: "commit:doc_m2_tx:1", PayloadDigest: events.Digest(body),
Producer: "docflow", OccurredAt: time.Now().UTC(), Payload: body,
}
boom := errors.New("boom after staging")
unit := uow.NewPG(pool)
err = unit.Within(ctx, func(scope uow.TxScope) error {
ctx = uow.WithScope(ctx, scope)
if err := (events.PGSink{}).Append(ctx, env, []string{"projection", "notify"}); err != nil {
return err
}
ing := &artifactvault.Ingest{Env: "dev"}
if err := ing.StageAgentCommit(ctx, 9, "doc_m2_tx", env.EventID, 4, body); err != nil {
return err
}
return boom
})
if !errors.Is(err, boom) {
t.Fatalf("want boom, got %v", err)
}
var envelopes, artifacts int
if err := pool.QueryRow(ctx, `SELECT COUNT(*) FROM event_envelopes WHERE event_id=$1`, env.EventID).Scan(&envelopes); err != nil {
t.Fatal(err)
}
if err := pool.QueryRow(ctx, `SELECT COUNT(*) FROM final_artifacts WHERE source_event_id=$1`, env.EventID).Scan(&artifacts); err != nil {
t.Fatal(err)
}
if envelopes != 0 || artifacts != 0 {
t.Fatalf("rollback leaked envelopes=%d artifacts=%d", envelopes, artifacts)
}
}