// Package app 承载 user-service App 注册表的 MySQL 持久化。 package app import ( "context" "database/sql" "strings" "hyapp/pkg/appcode" "hyapp/pkg/xerr" userdomain "hyapp/services/user-service/internal/domain/user" ) // Repository 读取 apps 注册表,供 gateway 把包名解析成内部 app_code。 type Repository struct { db *sql.DB } func New(db *sql.DB) *Repository { return &Repository{db: db} } // ResolveApp 按 app_code 或 package_name/platform 读取 active App。 func (r *Repository) ResolveApp(ctx context.Context, code string, packageName string, platform string) (userdomain.App, error) { if r == nil || r.db == nil { return userdomain.App{}, xerr.New(xerr.Unavailable, "app repository is not configured") } code = strings.TrimSpace(code) if code != "" { code = appcode.Normalize(code) } packageName = strings.TrimSpace(packageName) platform = strings.ToLower(strings.TrimSpace(platform)) var row *sql.Row if code != "" { row = r.db.QueryRowContext(ctx, ` SELECT app_id, app_code, app_name, package_name, platform, status, created_at_ms, updated_at_ms FROM apps WHERE app_code = ? AND status = ? LIMIT 1 `, code, userdomain.AppStatusActive) } else if packageName != "" { // gateway 首次请求通常只有包名;平台为空时允许命中任意平台配置,便于开发期客户端逐步补齐 header。 if platform == "" { row = r.db.QueryRowContext(ctx, ` SELECT app_id, app_code, app_name, package_name, platform, status, created_at_ms, updated_at_ms FROM apps WHERE package_name = ? AND status = ? ORDER BY platform DESC LIMIT 1 `, packageName, userdomain.AppStatusActive) } else { row = r.db.QueryRowContext(ctx, ` SELECT app_id, app_code, app_name, package_name, platform, status, created_at_ms, updated_at_ms FROM apps WHERE package_name = ? AND (platform = ? OR platform = '') AND status = ? ORDER BY CASE WHEN platform = ? THEN 0 ELSE 1 END LIMIT 1 `, packageName, platform, userdomain.AppStatusActive, platform) } } else { row = r.db.QueryRowContext(ctx, ` SELECT app_id, app_code, app_name, package_name, platform, status, created_at_ms, updated_at_ms FROM apps WHERE app_code = ? AND status = ? LIMIT 1 `, code, userdomain.AppStatusActive) } var app userdomain.App if err := row.Scan(&app.AppID, &app.AppCode, &app.AppName, &app.PackageName, &app.Platform, &app.Status, &app.CreatedAtMs, &app.UpdatedAtMs); err != nil { if err == sql.ErrNoRows { return userdomain.App{}, xerr.New(xerr.InvalidArgument, "app is not supported") } return userdomain.App{}, err } return app, nil }