package social import ( "context" "database/sql" "errors" "fmt" "github.com/jackc/pgx/v5/pgconn" ) // uniqueViolation is the PostgreSQL SQLSTATE for a unique-constraint violation. const uniqueViolation = "23505" // Store is the Postgres-backed query surface for the friend graph, per-user // blocks and per-game chat. type Store struct { db *sql.DB } // NewStore constructs a Store wrapping db. func NewStore(db *sql.DB) *Store { return &Store{db: db} } // isUniqueViolation reports whether err is a PostgreSQL unique-constraint // violation, used to collapse a request/insert race into a friendly error. func isUniqueViolation(err error) bool { var pgErr *pgconn.PgError return errors.As(err, &pgErr) && pgErr.Code == uniqueViolation } // withTx wraps fn in a transaction, committing on nil and rolling back on error. func withTx(ctx context.Context, db *sql.DB, fn func(tx *sql.Tx) error) error { tx, err := db.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("begin tx: %w", err) } if err := fn(tx); err != nil { _ = tx.Rollback() return err } if err := tx.Commit(); err != nil { return fmt.Errorf("commit tx: %w", err) } return nil }