You've already forked agentic-coding-workflow
feat(mcp,acp): Repository.WithTx + acp.Repository.InTx
Cross-module transactional support for spec §6.1: ACP CreateSession must atomically insert acp_sessions row + mcp_tokens row (FK NOT NULL). - mcp.Repository.WithTx(tx) -> Repository (tx-bound, no pool) - acp.Repository.InTx(ctx, fn) -> error (pgx.BeginFunc wrapper) - acp.Repository.WithTx(tx) -> Repository (tx-bound) - Update fakeRepos in test files to satisfy new interface methods Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,9 @@ type Repository interface {
|
||||
InsertEvent(ctx context.Context, e *Event) (*Event, error)
|
||||
ListEventsSince(ctx context.Context, sessionID uuid.UUID, sinceID int64, limit int32) ([]*Event, error)
|
||||
PurgeEventsBefore(ctx context.Context, before time.Time) (int64, error)
|
||||
|
||||
InTx(ctx context.Context, fn func(ctx context.Context, tx pgx.Tx) error) error
|
||||
WithTx(tx pgx.Tx) Repository
|
||||
}
|
||||
|
||||
// IsUniqueViolation reports whether err is a PG unique constraint violation
|
||||
@@ -74,6 +77,23 @@ func NewPostgresRepository(pool *pgxpool.Pool) Repository {
|
||||
return &pgRepo{pool: pool, q: acpsqlc.New(pool)}
|
||||
}
|
||||
|
||||
// InTx runs fn in a single transaction. Commits on nil error; rolls back
|
||||
// otherwise. Used by SessionService.Create to atomically insert acp_sessions
|
||||
// + mcp_tokens (spec §6.1).
|
||||
func (r *pgRepo) InTx(ctx context.Context, fn func(ctx context.Context, tx pgx.Tx) error) error {
|
||||
if r.pool == nil {
|
||||
return errs.New(errs.CodeInternal, "acp.Repository.InTx: nil pool (tx-bound instance)")
|
||||
}
|
||||
return pgx.BeginFunc(ctx, r.pool, func(tx pgx.Tx) error {
|
||||
return fn(ctx, tx)
|
||||
})
|
||||
}
|
||||
|
||||
// WithTx 返回绑定到指定事务的 Repository 副本。
|
||||
func (r *pgRepo) WithTx(tx pgx.Tx) Repository {
|
||||
return &pgRepo{pool: nil, q: r.q.WithTx(tx)}
|
||||
}
|
||||
|
||||
// ===== 类型转换 helper =====
|
||||
|
||||
func toPgUUID(u uuid.UUID) pgtype.UUID { return pgtype.UUID{Bytes: u, Valid: true} }
|
||||
|
||||
Reference in New Issue
Block a user