2026-05-14 00:25:02 +08:00

202 lines
6.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 config
import (
"net/http"
"strings"
"time"
"hyapp/pkg/configx"
"hyapp/pkg/logx"
"hyapp/pkg/tencentim"
)
// Config 描述 notice-service 启动配置。
type Config struct {
ServiceName string `yaml:"service_name"`
NodeID string `yaml:"node_id"`
Environment string `yaml:"environment"`
GRPCAddr string `yaml:"grpc_addr"`
// HealthHTTPAddr 给 CLB/发布脚本探活使用,不承载业务 HTTP。
HealthHTTPAddr string `yaml:"health_http_addr"`
// MySQLDSN 是 notice-service 自己的投递位点和死信状态库。
MySQLDSN string `yaml:"mysql_dsn"`
// WalletDatabase 是 wallet_outbox 所在库名notice 只把它当 append-only 事实源读取。
WalletDatabase string `yaml:"wallet_database"`
// RoomDatabase 是 room_outbox 所在库名notice 只读取需要私有通知的房间事实。
RoomDatabase string `yaml:"room_database"`
// TencentIM 是私有 IM 投递通道配置;本地默认关闭,避免误发真实消息。
TencentIM TencentIMConfig `yaml:"tencent_im"`
// WalletNoticeWorker 消费 wallet_outbox 中的 WalletBalanceChanged 事件。
WalletNoticeWorker WalletNoticeWorkerConfig `yaml:"wallet_notice_worker"`
// RoomNoticeWorker 消费 room_outbox 中需要给单个用户发送的房间通知。
RoomNoticeWorker WalletNoticeWorkerConfig `yaml:"room_notice_worker"`
MySQLAutoMigrate bool `yaml:"mysql_auto_migrate"`
Log logx.Config `yaml:"log"`
}
// TencentIMConfig 描述服务端调用腾讯云 IM REST API 的配置。
type TencentIMConfig struct {
Enabled bool `yaml:"enabled"`
SDKAppID int64 `yaml:"sdk_app_id"`
SecretKey string `yaml:"secret_key"`
AdminIdentifier string `yaml:"admin_identifier"`
AdminUserSigTTL time.Duration `yaml:"admin_user_sig_ttl"`
Endpoint string `yaml:"endpoint"`
RequestTimeout time.Duration `yaml:"request_timeout"`
}
// RESTConfig converts YAML config into shared Tencent IM REST config.
func (c TencentIMConfig) RESTConfig() tencentim.RESTConfig {
timeout := c.RequestTimeout
if timeout <= 0 {
timeout = 5 * time.Second
}
return tencentim.RESTConfig{
SDKAppID: c.SDKAppID,
SecretKey: c.SecretKey,
AdminIdentifier: c.AdminIdentifier,
AdminUserSigTTL: c.AdminUserSigTTL,
Endpoint: c.Endpoint,
HTTPClient: &http.Client{Timeout: timeout},
}
}
// WalletNoticeWorkerConfig 控制钱包私有通知投递 worker。
type WalletNoticeWorkerConfig struct {
Enabled bool `yaml:"enabled"`
PollInterval time.Duration `yaml:"poll_interval"`
BatchSize int `yaml:"batch_size"`
LockTTL time.Duration `yaml:"lock_ttl"`
PublishTimeout time.Duration `yaml:"publish_timeout"`
MaxRetryCount int `yaml:"max_retry_count"`
InitialBackoff time.Duration `yaml:"initial_backoff"`
MaxBackoff time.Duration `yaml:"max_backoff"`
}
// Default 返回本地开发默认配置。
func Default() Config {
return Config{
ServiceName: "notice-service",
NodeID: "notice-local",
Environment: "local",
GRPCAddr: ":13009",
HealthHTTPAddr: ":13109",
MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_notice?parseTime=true&charset=utf8mb4&loc=UTC",
WalletDatabase: "hyapp_wallet",
RoomDatabase: "hyapp_room",
MySQLAutoMigrate: false,
TencentIM: TencentIMConfig{
Enabled: false,
AdminIdentifier: "administrator",
AdminUserSigTTL: 24 * time.Hour,
Endpoint: tencentim.DefaultEndpoint,
RequestTimeout: 5 * time.Second,
},
WalletNoticeWorker: WalletNoticeWorkerConfig{
Enabled: false,
PollInterval: time.Second,
BatchSize: 100,
LockTTL: 30 * time.Second,
PublishTimeout: 3 * time.Second,
MaxRetryCount: 10,
InitialBackoff: 5 * time.Second,
MaxBackoff: 5 * time.Minute,
},
RoomNoticeWorker: WalletNoticeWorkerConfig{
Enabled: false,
PollInterval: time.Second,
BatchSize: 100,
LockTTL: 30 * time.Second,
PublishTimeout: 3 * time.Second,
MaxRetryCount: 10,
InitialBackoff: 5 * time.Second,
MaxBackoff: 5 * time.Minute,
},
Log: logx.Config{
Level: "info",
Format: "json",
MaxPayloadBytes: 2048,
},
}
}
// Load 从独立 config.yaml 读取 notice-service 配置。
func Load(path string) (Config, error) {
cfg := Default()
if path == "" {
return cfg, nil
}
if err := configx.LoadYAML(path, &cfg); err != nil {
return Config{}, err
}
cfg.ServiceName = strings.TrimSpace(cfg.ServiceName)
if cfg.ServiceName == "" {
cfg.ServiceName = "notice-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.GRPCAddr = strings.TrimSpace(cfg.GRPCAddr)
if cfg.GRPCAddr == "" {
cfg.GRPCAddr = ":13009"
}
cfg.HealthHTTPAddr = strings.TrimSpace(cfg.HealthHTTPAddr)
if cfg.HealthHTTPAddr == "" {
cfg.HealthHTTPAddr = ":13109"
}
cfg.WalletDatabase = strings.TrimSpace(cfg.WalletDatabase)
if cfg.WalletDatabase == "" {
cfg.WalletDatabase = "hyapp_wallet"
}
cfg.RoomDatabase = strings.TrimSpace(cfg.RoomDatabase)
if cfg.RoomDatabase == "" {
cfg.RoomDatabase = "hyapp_room"
}
cfg.WalletNoticeWorker = normalizeWalletNoticeWorker(cfg.WalletNoticeWorker)
cfg.RoomNoticeWorker = normalizeWalletNoticeWorker(cfg.RoomNoticeWorker)
if strings.TrimSpace(cfg.TencentIM.AdminIdentifier) == "" {
cfg.TencentIM.AdminIdentifier = "administrator"
}
if cfg.TencentIM.AdminUserSigTTL <= 0 {
cfg.TencentIM.AdminUserSigTTL = 24 * time.Hour
}
if strings.TrimSpace(cfg.TencentIM.Endpoint) == "" {
cfg.TencentIM.Endpoint = tencentim.DefaultEndpoint
}
if cfg.TencentIM.RequestTimeout <= 0 {
cfg.TencentIM.RequestTimeout = 5 * time.Second
}
return cfg, nil
}
func normalizeWalletNoticeWorker(cfg WalletNoticeWorkerConfig) WalletNoticeWorkerConfig {
def := Default().WalletNoticeWorker
if cfg.PollInterval <= 0 {
cfg.PollInterval = def.PollInterval
}
if cfg.BatchSize <= 0 {
cfg.BatchSize = def.BatchSize
}
if cfg.LockTTL <= 0 {
cfg.LockTTL = def.LockTTL
}
if cfg.PublishTimeout <= 0 {
cfg.PublishTimeout = def.PublishTimeout
}
if cfg.MaxRetryCount <= 0 {
cfg.MaxRetryCount = def.MaxRetryCount
}
if cfg.InitialBackoff <= 0 {
cfg.InitialBackoff = def.InitialBackoff
}
if cfg.MaxBackoff <= 0 {
cfg.MaxBackoff = def.MaxBackoff
}
return cfg
}