2026-04-25 13:21:39 +08:00

98 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package mysql
import (
"context"
"database/sql"
"errors"
"strings"
mysqldriver "github.com/go-sql-driver/mysql"
"hyapp/pkg/xerr"
)
// Repository 是 user-service 的 MySQL 持久化入口。
// 方法按领域拆到 user_repository、identity_repository 和 auth_repository避免一个文件混合多条业务线。
type Repository struct {
db *sql.DB
}
// Open 创建 MySQL 连接池并做启动 ping。
func Open(ctx context.Context, dsn string) (*Repository, error) {
if strings.TrimSpace(dsn) == "" {
return nil, xerr.New(xerr.InvalidArgument, "mysql_dsn is required")
}
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
if err := db.PingContext(ctx); err != nil {
_ = db.Close()
return nil, err
}
return &Repository{db: db}, nil
}
// Close 释放 MySQL 连接池。
func (r *Repository) Close() error {
if r == nil || r.db == nil {
return nil
}
return r.db.Close()
}
// Ping 验证 MySQL 当前可用。
func (r *Repository) Ping(ctx context.Context) error {
if r == nil || r.db == nil {
return xerr.New(xerr.Unavailable, "mysql repository is not configured")
}
return r.db.PingContext(ctx)
}
// mapDuplicateError 把通用 display_user_id 唯一冲突转换成稳定领域 reason。
func mapDuplicateError(err error) error {
var mysqlErr *mysqldriver.MySQLError
if errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 {
return xerr.New(xerr.DisplayUserIDExists, "display_user_id already exists")
}
return err
}
// mapPrettyDuplicateError 把靓号租约相关唯一冲突转换成靓号不可用。
func mapPrettyDuplicateError(err error) error {
var mysqlErr *mysqldriver.MySQLError
if errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 {
return xerr.New(xerr.DisplayUserIDPrettyNotAvailable, "pretty display_user_id is not available")
}
return err
}
// nullableString 统一把空字符串写成 SQL NULL避免空值参与唯一性或审计语义。
func nullableString(value string) any {
if strings.TrimSpace(value) == "" {
return nil
}
return value
}
// nullableOperator 让系统修改短号时可以不携带 operator_user_id。
func nullableOperator(operatorUserID int64) any {
if operatorUserID <= 0 {
return nil
}
return operatorUserID
}
// queryer 抽象 *sql.DB 和 *sql.Tx 的 QueryRowContext便于读方法复用事务锁定查询。
type queryer interface {
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}