2026-05-09 21:47:33 +08:00

227 lines
8.7 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 config 定义 user-service 的启动配置和 YAML 加载入口。
package config
import (
"strings"
"hyapp/pkg/configx"
"hyapp/pkg/logx"
)
// Config 描述 user-service 启动配置。
type Config struct {
// ServiceName 是进程服务名,当前主要用于配置可读性。
ServiceName string `yaml:"service_name"`
// NodeID 是当前服务节点标识,预留给日志和后续健康响应使用。
NodeID string `yaml:"node_id"`
// Environment 是日志和部署策略使用的环境标签。
Environment string `yaml:"environment"`
// GRPCAddr 是 user-service 内部 gRPC 监听地址。
GRPCAddr string `yaml:"grpc_addr"`
// MySQLDSN 是用户主数据、认证身份、session 和短号事务的必需存储连接串。
MySQLDSN string `yaml:"mysql_dsn"`
// MySQLAutoMigrate 保留给显式本地迁移;线上 schema 由发布流程或 initdb 管理。
MySQLAutoMigrate bool `yaml:"mysql_auto_migrate"`
// IDGenerator 控制 user_id 发号节点。
IDGenerator IDGeneratorConfig `yaml:"id_generator"`
// DisplayUserID 控制短号分配重试和默认短号修改冷却期。
DisplayUserID DisplayUserIDConfig `yaml:"display_user_id"`
// ThirdParty 控制本地三方登录 provider allowlist。
ThirdParty ThirdPartyConfig `yaml:"third_party"`
// InviteRechargeWorker 控制邀请有效人数的 wallet recharge outbox 消费。
InviteRechargeWorker InviteRechargeWorkerConfig `yaml:"invite_recharge_worker"`
// MicTimeWorker 控制 room-service 麦位事件消费和用户麦上时长聚合。
MicTimeWorker MicTimeWorkerConfig `yaml:"mic_time_worker"`
// LoginRisk 控制登录后 IP 风控策略、Redis session denylist 和 IP 查询 provider。
LoginRisk LoginRiskConfig `yaml:"login_risk"`
// JWT 控制 access token 和 refresh session 的签发参数。
JWT JWTConfig `yaml:"jwt"`
// Log 控制 stdout 结构化日志格式、等级和 access body 策略。
Log logx.Config `yaml:"log"`
}
// LoginRiskConfig 保存登录地区风控的 Redis、TTL 和 provider 顺序;后台扫描由 cron-service 调度。
type LoginRiskConfig struct {
Enabled bool `yaml:"enabled"`
RedisAddr string `yaml:"redis_addr"`
RedisPassword string `yaml:"redis_password"`
RedisDB int `yaml:"redis_db"`
UnsupportedCountries []string `yaml:"unsupported_countries"`
BlockedTTLSec int64 `yaml:"blocked_ttl_sec"`
AllowedTTLSec int64 `yaml:"allowed_ttl_sec"`
UnknownTTLSec int64 `yaml:"unknown_ttl_sec"`
ProviderTimeoutMs int64 `yaml:"provider_timeout_ms"`
Providers []string `yaml:"providers"`
}
// IDGeneratorConfig 保存 user_id 发号节点配置。
type IDGeneratorConfig struct {
// NodeID 参与雪花 ID 发号,多个 user-service 节点必须不同。
NodeID int64 `yaml:"node_id"`
}
// DisplayUserIDConfig 保存短号分配和修改策略。
type DisplayUserIDConfig struct {
// AllocateMaxAttempts 是默认短号冲突时的最大重试次数。
AllocateMaxAttempts int `yaml:"allocate_max_attempts"`
// ChangeCooldownSec 是默认短号修改冷却期秒数。
ChangeCooldownSec int64 `yaml:"change_cooldown_sec"`
}
// ThirdPartyConfig 保存三方登录 provider allowlist 和真实 verifier 配置。
type ThirdPartyConfig struct {
// AllowedProviders 是 provider allowlistfirebase 会被强制路由到 Firebase verifier。
AllowedProviders []string `yaml:"allowed_providers"`
// Firebase 保存 Firebase Auth ID token verifier 配置。
Firebase FirebaseConfig `yaml:"firebase"`
}
// FirebaseConfig 保存 Firebase Auth ID token verifier 配置。
type FirebaseConfig struct {
// ProjectID 必须匹配 Firebase token 的 aud 和 issuer。
ProjectID string `yaml:"project_id"`
// AllowedSignInProviders 限制 firebase.sign_in_provider首版默认 google.com。
AllowedSignInProviders []string `yaml:"allowed_sign_in_providers"`
// CertsURL 只用于测试或私有代理;生产为空时使用 Firebase 官方公钥端点。
CertsURL string `yaml:"certs_url"`
}
// InviteRechargeWorkerConfig 保存钱包充值事实消费策略。
type InviteRechargeWorkerConfig struct {
// Enabled 控制是否启动钱包充值事件轮询。
Enabled bool `yaml:"enabled"`
// WalletMySQLDSN 是 wallet-service outbox 只读连接串;本地可复用同一个 MySQL 实例。
WalletMySQLDSN string `yaml:"wallet_mysql_dsn"`
// PollIntervalSec 是没有积压时两轮扫描间隔秒数。
PollIntervalSec int64 `yaml:"poll_interval_sec"`
// BatchSize 是单轮最多消费的 wallet_outbox 事件数。
BatchSize int `yaml:"batch_size"`
}
// MicTimeWorkerConfig 保存房间麦位事件消费策略。
type MicTimeWorkerConfig struct {
// Enabled 控制是否启动 room_outbox 轮询;关闭后查询仍可读取已聚合数据。
Enabled bool `yaml:"enabled"`
// RoomMySQLDSN 是 room-service outbox 只读连接串。
RoomMySQLDSN string `yaml:"room_mysql_dsn"`
// PollIntervalSec 是没有积压时两轮扫描间隔秒数。
PollIntervalSec int64 `yaml:"poll_interval_sec"`
// BatchSize 是单轮最多消费的 RoomMicChanged 事件数。
BatchSize int `yaml:"batch_size"`
}
// JWTConfig 保存 access token 和 refresh token 的签发策略。
type JWTConfig struct {
// Issuer 写入 access token iss claim。
Issuer string `yaml:"issuer"`
// AccessTokenTTLSec 是短期 access token 有效期。
AccessTokenTTLSec int64 `yaml:"access_token_ttl_sec"`
// RefreshTokenTTLSec 是服务端 session/refresh token 有效期。
RefreshTokenTTLSec int64 `yaml:"refresh_token_ttl_sec"`
// SigningAlg 当前只支持 HS256。
SigningAlg string `yaml:"signing_alg"`
// SigningSecret 是 HS256 签名密钥,生产不能使用默认开发值。
SigningSecret string `yaml:"signing_secret"`
}
// Default 返回本地默认配置。
func Default() Config {
// 默认端口遵守项目 13xxx 约束;本地进程默认连接 docker-compose 暴露的 MySQL。
return Config{
ServiceName: "user-service",
NodeID: "user-local",
Environment: "local",
GRPCAddr: ":13005",
MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_user?parseTime=true&charset=utf8mb4&loc=Local",
MySQLAutoMigrate: false,
IDGenerator: IDGeneratorConfig{
NodeID: 1,
},
DisplayUserID: DisplayUserIDConfig{
AllocateMaxAttempts: 8,
ChangeCooldownSec: 2592000,
},
ThirdParty: ThirdPartyConfig{
AllowedProviders: []string{"firebase"},
Firebase: FirebaseConfig{
AllowedSignInProviders: []string{"google.com"},
},
},
InviteRechargeWorker: InviteRechargeWorkerConfig{
Enabled: true,
WalletMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=Local",
PollIntervalSec: 5,
BatchSize: 100,
},
MicTimeWorker: MicTimeWorkerConfig{
Enabled: true,
RoomMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_room?parseTime=true&charset=utf8mb4&loc=Local",
PollIntervalSec: 5,
BatchSize: 100,
},
LoginRisk: LoginRiskConfig{
Enabled: true,
RedisAddr: "127.0.0.1:13379",
UnsupportedCountries: []string{"CN"},
BlockedTTLSec: 2592000,
AllowedTTLSec: 604800,
UnknownTTLSec: 1800,
ProviderTimeoutMs: 800,
Providers: []string{"edge_country"},
},
JWT: JWTConfig{
Issuer: "hyapp",
AccessTokenTTLSec: 1800,
RefreshTokenTTLSec: 2592000,
SigningAlg: "HS256",
SigningSecret: "dev-shared-secret",
},
Log: logx.Config{
Level: "info",
Format: "json",
MaxPayloadBytes: 2048,
},
}
}
// Load 从独立 config.yaml 读取 user-service 配置。
func Load(path string) (Config, error) {
cfg := Default()
if path == "" {
// 空路径显式使用默认配置,便于单元测试和最小启动。
return cfg, nil
}
if err := configx.LoadYAML(path, &cfg); err != nil {
// 配置解析失败返回空 Config避免调用方误用部分默认值继续启动。
return Config{}, err
}
cfg.ServiceName = strings.TrimSpace(cfg.ServiceName)
if cfg.ServiceName == "" {
cfg.ServiceName = "user-service"
}
cfg.NodeID = strings.TrimSpace(cfg.NodeID)
if cfg.NodeID == "" {
cfg.NodeID = cfg.ServiceName
}
cfg.Environment = strings.ToLower(strings.TrimSpace(cfg.Environment))
if cfg.Environment == "" {
cfg.Environment = "local"
}
cfg.LoginRisk.RedisAddr = strings.TrimSpace(cfg.LoginRisk.RedisAddr)
if cfg.LoginRisk.BlockedTTLSec <= 0 {
cfg.LoginRisk.BlockedTTLSec = 2592000
}
if cfg.LoginRisk.AllowedTTLSec <= 0 {
cfg.LoginRisk.AllowedTTLSec = 604800
}
if cfg.LoginRisk.UnknownTTLSec <= 0 {
cfg.LoginRisk.UnknownTTLSec = 1800
}
if cfg.LoginRisk.ProviderTimeoutMs <= 0 {
cfg.LoginRisk.ProviderTimeoutMs = 800
}
return cfg, nil
}