538 lines
24 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 (
"errors"
"net/http"
"strings"
"time"
"hyapp/pkg/configx"
"hyapp/pkg/logx"
"hyapp/pkg/tencentim"
)
// Config 描述 activity-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 是活动状态、事件消费幂等和 outbox 的必需存储连接串。
MySQLDSN string `yaml:"mysql_dsn"`
// UserServiceAddr 是 fanout worker 读取目标用户游标的内部 gRPC 地址。
UserServiceAddr string `yaml:"user_service_addr"`
// WalletServiceAddr 是任务奖励入账依赖activity 只发命令,不直接写余额。
WalletServiceAddr string `yaml:"wallet_service_addr"`
// RoomServiceAddr 是房间流水奖励结算读取房主快照的内部 gRPC 地址。
RoomServiceAddr string `yaml:"room_service_addr"`
// FirstRechargeRewardWorker 控制首冲奖励对 wallet_outbox 充值事实的本地消费。
FirstRechargeRewardWorker FirstRechargeRewardWorkerConfig `yaml:"first_recharge_reward_worker"`
// CumulativeRechargeRewardWorker 控制累充奖励对 wallet_outbox 充值事实的本地消费。
CumulativeRechargeRewardWorker CumulativeRechargeRewardWorkerConfig `yaml:"cumulative_recharge_reward_worker"`
// InviteActivityRewardWorker 控制邀请活动对 wallet/user outbox 事实的本地消费。
InviteActivityRewardWorker InviteActivityRewardWorkerConfig `yaml:"invite_activity_reward_worker"`
// RedPacketBroadcastWorker 控制红包创建事实转区域飘屏 outbox 的本地消费。
RedPacketBroadcastWorker RedPacketBroadcastWorkerConfig `yaml:"red_packet_broadcast_worker"`
// TaskEventWorker 控制任务系统对 wallet/user outbox 事实的本地消费。
TaskEventWorker TaskEventWorkerConfig `yaml:"task_event_worker"`
// UserLeaderboardWorker 控制用户送礼榜单对 wallet_outbox 送礼事实的 Redis 投影。
UserLeaderboardWorker UserLeaderboardWorkerConfig `yaml:"user_leaderboard_worker"`
// TencentIM 是 activity-service 发送全局/区域播报群消息的 REST 配置。
TencentIM TencentIMConfig `yaml:"tencent_im"`
// Broadcast 控制 IM 播报群 reconciler、outbox worker 和贵重礼物阈值。
Broadcast BroadcastConfig `yaml:"broadcast"`
// RocketMQ 可直接消费 room-service 发布的 room_outbox fanout topic。
RocketMQ RocketMQConfig `yaml:"rocketmq"`
// MySQLAutoMigrate 保留给显式本地迁移;线上 schema 由发布流程或 initdb 管理。
MySQLAutoMigrate bool `yaml:"mysql_auto_migrate"`
Consumer ConsumerConfig `yaml:"consumer"`
MessageInbox MessageInboxConfig `yaml:"message_inbox"`
// MessageActionConfirmWorker 控制通用确认消息的 user_outbox 消费和 IM outbox 发布。
MessageActionConfirmWorker MessageActionConfirmWorkerConfig `yaml:"message_action_confirm_worker"`
Log logx.Config `yaml:"log"`
}
// ConsumerConfig 保存 room outbox 消费底座配置。
type ConsumerConfig struct {
RoomOutboxPollIntervalMs int64 `yaml:"room_outbox_poll_interval_ms"`
BatchSize int `yaml:"batch_size"`
}
// MessageInboxConfig 保存 App system/activity inbox 的读取缓存参数fanout 扫描由 cron-service 调度。
type MessageInboxConfig struct {
UnreadCacheTTL string `yaml:"unread_cache_ttl"`
}
// MessageActionConfirmWorkerConfig 保存确认消息消费和 MQ 发布策略。
type MessageActionConfirmWorkerConfig struct {
Enabled bool `yaml:"enabled"`
OutboxPollInterval time.Duration `yaml:"outbox_poll_interval"`
OutboxBatchSize int `yaml:"outbox_batch_size"`
OutboxLockTTL time.Duration `yaml:"outbox_lock_ttl"`
OutboxMaxRetry int `yaml:"outbox_max_retry"`
PublishTimeout time.Duration `yaml:"publish_timeout"`
}
// FirstRechargeRewardWorkerConfig 保存钱包充值事实消费策略。
type FirstRechargeRewardWorkerConfig struct {
// Enabled 控制是否启动 wallet_outbox MQ 消费;关闭后仍可通过 gRPC 消费入口补偿。
Enabled bool `yaml:"enabled"`
}
// CumulativeRechargeRewardWorkerConfig 保存累充奖励钱包充值事实消费策略。
type CumulativeRechargeRewardWorkerConfig struct {
// Enabled 控制是否启动 wallet_outbox MQ 消费;关闭后仍可通过 gRPC 消费入口补偿。
Enabled bool `yaml:"enabled"`
}
// InviteActivityRewardWorkerConfig 保存邀请活动钱包和用户事实消费策略。
type InviteActivityRewardWorkerConfig struct {
// Enabled 控制是否启动 wallet/user outbox MQ 消费。
Enabled bool `yaml:"enabled"`
}
// RedPacketBroadcastWorkerConfig 保存红包创建事实消费策略。
type RedPacketBroadcastWorkerConfig struct {
// Enabled 控制是否启动 wallet_outbox MQ 消费。
Enabled bool `yaml:"enabled"`
}
// TaskEventWorkerConfig 保存任务进度事实消费策略。
type TaskEventWorkerConfig struct {
// Enabled 控制是否启动 wallet/user outbox 任务消费者room outbox 任务投影跟随 room_outbox 主消费者。
Enabled bool `yaml:"enabled"`
}
// UserLeaderboardWorkerConfig 保存用户送礼榜单 Redis 投影策略。
type UserLeaderboardWorkerConfig struct {
// Enabled 控制是否启动 wallet_outbox 用户榜单消费者;关闭时 gateway 只能读到已有 Redis 聚合。
Enabled bool `yaml:"enabled"`
// RedisAddr 是 activity 写入用户榜单聚合的 Redis 地址,必须与 gateway 读取地址一致。
RedisAddr string `yaml:"redis_addr"`
// RedisPassword 是 Redis 鉴权密码,本地默认留空。
RedisPassword string `yaml:"redis_password"`
// RedisDB 是 Redis logical DB必须与 gateway 读取配置一致。
RedisDB int `yaml:"redis_db"`
// KeyPrefix 隔离用户榜单 key必须与 gateway 读取配置一致。
KeyPrefix string `yaml:"key_prefix"`
}
// TencentIMConfig 描述 activity-service 调用腾讯云 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"`
GroupType string `yaml:"group_type"`
GroupIDPrefix string `yaml:"group_id_prefix"`
RequestTimeout time.Duration `yaml:"request_timeout"`
}
// RESTConfig converts YAML into the shared Tencent IM REST client 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,
GroupType: c.GroupType,
HTTPClient: &http.Client{Timeout: timeout},
}
}
// BroadcastConfig stores activity-service broadcast worker policy.
type BroadcastConfig struct {
Enabled bool `yaml:"enabled"`
SuperGiftMinValue int64 `yaml:"super_gift_min_value"`
WorkerPollInterval time.Duration `yaml:"worker_poll_interval"`
WorkerBatchSize int `yaml:"worker_batch_size"`
WorkerLockTTL time.Duration `yaml:"worker_lock_ttl"`
WorkerMaxRetry int `yaml:"worker_max_retry"`
EnsureGroupsOnStartup bool `yaml:"ensure_groups_on_startup"`
// EnsureGroupsInterval 是播报群定时 reconcile 周期0 表示只在启动时补偿一次。
// 新区域上线或启动补偿失败时靠它自动补群,不再依赖人工调用 gRPC。
EnsureGroupsInterval time.Duration `yaml:"ensure_groups_interval"`
}
// RocketMQConfig 描述 activity-service 消费房间事实的 MQ 连接。
type RocketMQConfig struct {
Enabled bool `yaml:"enabled"`
NameServers []string `yaml:"name_servers"`
NameServerDomain string `yaml:"name_server_domain"`
AccessKey string `yaml:"access_key"`
SecretKey string `yaml:"secret_key"`
SecurityToken string `yaml:"security_token"`
Namespace string `yaml:"namespace"`
VIPChannel bool `yaml:"vip_channel"`
RoomOutbox RoomOutboxMQConfig `yaml:"room_outbox"`
WalletOutbox WalletOutboxMQConfig `yaml:"wallet_outbox"`
UserOutbox UserOutboxMQConfig `yaml:"user_outbox"`
MessageActionOutbox MessageActionOutboxMQConfig `yaml:"message_action_outbox"`
}
// RoomOutboxMQConfig 控制 activity 对 room_outbox topic 的消费位点。
type RoomOutboxMQConfig struct {
Enabled bool `yaml:"enabled"`
Topic string `yaml:"topic"`
ConsumerGroup string `yaml:"consumer_group"`
ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"`
}
// WalletOutboxMQConfig 控制 activity 对 wallet_outbox topic 的独立消费组。
type WalletOutboxMQConfig struct {
Enabled bool `yaml:"enabled"`
Topic string `yaml:"topic"`
RealtimeTopic string `yaml:"realtime_topic"`
FirstRechargeConsumerGroup string `yaml:"first_recharge_consumer_group"`
CumulativeRechargeConsumerGroup string `yaml:"cumulative_recharge_consumer_group"`
InviteActivityConsumerGroup string `yaml:"invite_activity_consumer_group"`
RedPacketBroadcastConsumerGroup string `yaml:"red_packet_broadcast_consumer_group"`
TaskConsumerGroup string `yaml:"task_consumer_group"`
UserLeaderboardConsumerGroup string `yaml:"user_leaderboard_consumer_group"`
ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"`
}
// UserOutboxMQConfig 控制 activity 对 user_outbox topic 的独立消费组。
type UserOutboxMQConfig struct {
Enabled bool `yaml:"enabled"`
Topic string `yaml:"topic"`
ConsumerGroup string `yaml:"consumer_group"`
TaskConsumerGroup string `yaml:"task_consumer_group"`
InviteActivityConsumerGroup string `yaml:"invite_activity_consumer_group"`
MessageActionConsumerGroup string `yaml:"message_action_consumer_group"`
ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"`
}
// MessageActionOutboxMQConfig 控制确认消息 outbox 投递到 notice-service 的 MQ producer。
type MessageActionOutboxMQConfig struct {
Enabled bool `yaml:"enabled"`
Topic string `yaml:"topic"`
ProducerGroup string `yaml:"producer_group"`
SendTimeout time.Duration `yaml:"send_timeout"`
Retry int `yaml:"retry"`
}
// Default 返回本地默认配置。
func Default() Config {
return Config{
ServiceName: "activity-service",
NodeID: "activity-local",
Environment: "local",
GRPCAddr: ":13006",
HealthHTTPAddr: ":13106",
MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC",
UserServiceAddr: "127.0.0.1:13005",
WalletServiceAddr: "127.0.0.1:13004",
RoomServiceAddr: "127.0.0.1:13001",
FirstRechargeRewardWorker: FirstRechargeRewardWorkerConfig{
Enabled: false,
},
CumulativeRechargeRewardWorker: CumulativeRechargeRewardWorkerConfig{
Enabled: false,
},
InviteActivityRewardWorker: InviteActivityRewardWorkerConfig{
Enabled: true,
},
RedPacketBroadcastWorker: RedPacketBroadcastWorkerConfig{
Enabled: false,
},
TaskEventWorker: TaskEventWorkerConfig{
Enabled: true,
},
UserLeaderboardWorker: UserLeaderboardWorkerConfig{
Enabled: false,
},
MessageActionConfirmWorker: MessageActionConfirmWorkerConfig{
Enabled: true,
OutboxPollInterval: time.Second,
OutboxBatchSize: 100,
OutboxLockTTL: 30 * time.Second,
OutboxMaxRetry: 8,
PublishTimeout: 5 * time.Second,
},
TencentIM: TencentIMConfig{
Enabled: false,
AdminIdentifier: "administrator",
AdminUserSigTTL: 24 * time.Hour,
Endpoint: tencentim.DefaultEndpoint,
GroupType: tencentim.DefaultGroupType,
RequestTimeout: 5 * time.Second,
},
Broadcast: BroadcastConfig{
Enabled: false,
SuperGiftMinValue: 100000,
WorkerPollInterval: time.Second,
WorkerBatchSize: 100,
WorkerLockTTL: 30 * time.Second,
WorkerMaxRetry: 8,
EnsureGroupsOnStartup: true,
EnsureGroupsInterval: 30 * time.Minute,
},
RocketMQ: defaultRocketMQConfig(),
MySQLAutoMigrate: false,
Consumer: ConsumerConfig{
RoomOutboxPollIntervalMs: 1000,
BatchSize: 100,
},
MessageInbox: MessageInboxConfig{
UnreadCacheTTL: "60s",
},
Log: logx.Config{
Level: "info",
Format: "json",
MaxPayloadBytes: 2048,
},
}
}
func defaultRocketMQConfig() RocketMQConfig {
return RocketMQConfig{
Enabled: false,
RoomOutbox: RoomOutboxMQConfig{
Enabled: false,
Topic: "hyapp_room_outbox",
ConsumerGroup: "hyapp-activity-room-outbox",
ConsumerMaxReconsumeTimes: 16,
},
WalletOutbox: WalletOutboxMQConfig{
Enabled: false,
Topic: "hyapp_wallet_outbox",
RealtimeTopic: "",
FirstRechargeConsumerGroup: "hyapp-activity-first-recharge-wallet-outbox",
CumulativeRechargeConsumerGroup: "hyapp-activity-cumulative-recharge-wallet-outbox",
InviteActivityConsumerGroup: "hyapp-activity-invite-wallet-outbox",
RedPacketBroadcastConsumerGroup: "hyapp-activity-red-packet-wallet-outbox",
TaskConsumerGroup: "hyapp-activity-task-wallet-outbox",
UserLeaderboardConsumerGroup: "hyapp-activity-user-leaderboard-wallet-outbox",
ConsumerMaxReconsumeTimes: 16,
},
UserOutbox: UserOutboxMQConfig{
Enabled: false,
Topic: "hyapp_user_outbox",
ConsumerGroup: "hyapp-activity-user-region-broadcast",
TaskConsumerGroup: "hyapp-activity-task-user-outbox",
InviteActivityConsumerGroup: "hyapp-activity-invite-user-outbox",
MessageActionConsumerGroup: "hyapp-activity-message-action-user-outbox",
ConsumerMaxReconsumeTimes: 16,
},
MessageActionOutbox: MessageActionOutboxMQConfig{
Enabled: false,
Topic: "hyapp_message_action_outbox",
ProducerGroup: "hyapp-activity-message-action-outbox",
SendTimeout: 5 * time.Second,
Retry: 2,
},
}
}
// Load 从独立 config.yaml 读取 activity-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
}
if strings.TrimSpace(cfg.UserServiceAddr) == "" {
cfg.UserServiceAddr = Default().UserServiceAddr
}
if strings.TrimSpace(cfg.WalletServiceAddr) == "" {
cfg.WalletServiceAddr = Default().WalletServiceAddr
}
if strings.TrimSpace(cfg.RoomServiceAddr) == "" {
cfg.RoomServiceAddr = Default().RoomServiceAddr
}
cfg.ServiceName = strings.TrimSpace(cfg.ServiceName)
if cfg.ServiceName == "" {
cfg.ServiceName = "activity-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.HealthHTTPAddr = strings.TrimSpace(cfg.HealthHTTPAddr)
if cfg.HealthHTTPAddr == "" {
cfg.HealthHTTPAddr = ":13106"
}
cfg.TencentIM.AdminIdentifier = strings.TrimSpace(cfg.TencentIM.AdminIdentifier)
if cfg.TencentIM.AdminIdentifier == "" {
cfg.TencentIM.AdminIdentifier = "administrator"
}
cfg.TencentIM.Endpoint = strings.TrimSpace(cfg.TencentIM.Endpoint)
if cfg.TencentIM.Endpoint == "" {
cfg.TencentIM.Endpoint = tencentim.DefaultEndpoint
}
cfg.TencentIM.GroupType = strings.TrimSpace(cfg.TencentIM.GroupType)
if cfg.TencentIM.GroupType == "" {
cfg.TencentIM.GroupType = tencentim.DefaultGroupType
}
cfg.TencentIM.GroupIDPrefix = strings.TrimSpace(cfg.TencentIM.GroupIDPrefix)
if cfg.TencentIM.AdminUserSigTTL <= 0 {
cfg.TencentIM.AdminUserSigTTL = 24 * time.Hour
}
if cfg.TencentIM.RequestTimeout <= 0 {
cfg.TencentIM.RequestTimeout = 5 * time.Second
}
if cfg.Broadcast.SuperGiftMinValue <= 0 {
cfg.Broadcast.SuperGiftMinValue = 100000
}
if cfg.Broadcast.WorkerPollInterval <= 0 {
cfg.Broadcast.WorkerPollInterval = time.Second
}
if cfg.Broadcast.WorkerBatchSize <= 0 {
cfg.Broadcast.WorkerBatchSize = 100
}
if cfg.Broadcast.WorkerLockTTL <= 0 {
cfg.Broadcast.WorkerLockTTL = 30 * time.Second
}
if cfg.Broadcast.WorkerMaxRetry <= 0 {
cfg.Broadcast.WorkerMaxRetry = 8
}
if cfg.MessageActionConfirmWorker.OutboxPollInterval <= 0 {
cfg.MessageActionConfirmWorker.OutboxPollInterval = time.Second
}
if cfg.MessageActionConfirmWorker.OutboxBatchSize <= 0 {
cfg.MessageActionConfirmWorker.OutboxBatchSize = 100
}
if cfg.MessageActionConfirmWorker.OutboxLockTTL <= 0 {
cfg.MessageActionConfirmWorker.OutboxLockTTL = 30 * time.Second
}
if cfg.MessageActionConfirmWorker.OutboxMaxRetry <= 0 {
cfg.MessageActionConfirmWorker.OutboxMaxRetry = 8
}
if cfg.MessageActionConfirmWorker.PublishTimeout <= 0 {
cfg.MessageActionConfirmWorker.PublishTimeout = 5 * time.Second
}
cfg.UserLeaderboardWorker.RedisAddr = strings.TrimSpace(cfg.UserLeaderboardWorker.RedisAddr)
cfg.UserLeaderboardWorker.KeyPrefix = strings.TrimSpace(cfg.UserLeaderboardWorker.KeyPrefix)
rocketMQ, err := normalizeRocketMQConfig(cfg.RocketMQ)
if err != nil {
return Config{}, err
}
cfg.RocketMQ = rocketMQ
if (cfg.FirstRechargeRewardWorker.Enabled || cfg.CumulativeRechargeRewardWorker.Enabled || cfg.InviteActivityRewardWorker.Enabled || cfg.RedPacketBroadcastWorker.Enabled || cfg.UserLeaderboardWorker.Enabled) && !cfg.RocketMQ.WalletOutbox.Enabled {
return Config{}, errors.New("wallet outbox workers require rocketmq.wallet_outbox.enabled")
}
if cfg.UserLeaderboardWorker.Enabled && cfg.UserLeaderboardWorker.RedisAddr == "" {
return Config{}, errors.New("user leaderboard worker requires redis_addr")
}
if cfg.InviteActivityRewardWorker.Enabled && !cfg.RocketMQ.UserOutbox.Enabled {
return Config{}, errors.New("invite activity reward worker requires rocketmq.user_outbox.enabled")
}
if cfg.MessageActionConfirmWorker.Enabled && (!cfg.RocketMQ.UserOutbox.Enabled || !cfg.RocketMQ.MessageActionOutbox.Enabled) {
return Config{}, errors.New("message action confirm worker requires rocketmq.user_outbox.enabled and rocketmq.message_action_outbox.enabled")
}
return cfg, nil
}
func normalizeRocketMQConfig(cfg RocketMQConfig) (RocketMQConfig, error) {
defaults := defaultRocketMQConfig()
cfg.NameServers = normalizeStringSlice(cfg.NameServers)
cfg.NameServerDomain = strings.TrimSpace(cfg.NameServerDomain)
cfg.AccessKey = strings.TrimSpace(cfg.AccessKey)
cfg.SecretKey = strings.TrimSpace(cfg.SecretKey)
cfg.SecurityToken = strings.TrimSpace(cfg.SecurityToken)
cfg.Namespace = strings.TrimSpace(cfg.Namespace)
if cfg.RoomOutbox.Topic = strings.TrimSpace(cfg.RoomOutbox.Topic); cfg.RoomOutbox.Topic == "" {
cfg.RoomOutbox.Topic = defaults.RoomOutbox.Topic
}
if cfg.RoomOutbox.ConsumerGroup = strings.TrimSpace(cfg.RoomOutbox.ConsumerGroup); cfg.RoomOutbox.ConsumerGroup == "" {
cfg.RoomOutbox.ConsumerGroup = defaults.RoomOutbox.ConsumerGroup
}
if cfg.RoomOutbox.ConsumerMaxReconsumeTimes <= 0 {
cfg.RoomOutbox.ConsumerMaxReconsumeTimes = defaults.RoomOutbox.ConsumerMaxReconsumeTimes
}
if cfg.WalletOutbox.Topic = strings.TrimSpace(cfg.WalletOutbox.Topic); cfg.WalletOutbox.Topic == "" {
cfg.WalletOutbox.Topic = defaults.WalletOutbox.Topic
}
cfg.WalletOutbox.RealtimeTopic = strings.TrimSpace(cfg.WalletOutbox.RealtimeTopic)
if cfg.WalletOutbox.FirstRechargeConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.FirstRechargeConsumerGroup); cfg.WalletOutbox.FirstRechargeConsumerGroup == "" {
cfg.WalletOutbox.FirstRechargeConsumerGroup = defaults.WalletOutbox.FirstRechargeConsumerGroup
}
if cfg.WalletOutbox.CumulativeRechargeConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.CumulativeRechargeConsumerGroup); cfg.WalletOutbox.CumulativeRechargeConsumerGroup == "" {
cfg.WalletOutbox.CumulativeRechargeConsumerGroup = defaults.WalletOutbox.CumulativeRechargeConsumerGroup
}
if cfg.WalletOutbox.InviteActivityConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.InviteActivityConsumerGroup); cfg.WalletOutbox.InviteActivityConsumerGroup == "" {
cfg.WalletOutbox.InviteActivityConsumerGroup = defaults.WalletOutbox.InviteActivityConsumerGroup
}
if cfg.WalletOutbox.RedPacketBroadcastConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.RedPacketBroadcastConsumerGroup); cfg.WalletOutbox.RedPacketBroadcastConsumerGroup == "" {
cfg.WalletOutbox.RedPacketBroadcastConsumerGroup = defaults.WalletOutbox.RedPacketBroadcastConsumerGroup
}
if cfg.WalletOutbox.TaskConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.TaskConsumerGroup); cfg.WalletOutbox.TaskConsumerGroup == "" {
cfg.WalletOutbox.TaskConsumerGroup = defaults.WalletOutbox.TaskConsumerGroup
}
if cfg.WalletOutbox.UserLeaderboardConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.UserLeaderboardConsumerGroup); cfg.WalletOutbox.UserLeaderboardConsumerGroup == "" {
cfg.WalletOutbox.UserLeaderboardConsumerGroup = defaults.WalletOutbox.UserLeaderboardConsumerGroup
}
if cfg.WalletOutbox.ConsumerMaxReconsumeTimes <= 0 {
cfg.WalletOutbox.ConsumerMaxReconsumeTimes = defaults.WalletOutbox.ConsumerMaxReconsumeTimes
}
if cfg.UserOutbox.Topic = strings.TrimSpace(cfg.UserOutbox.Topic); cfg.UserOutbox.Topic == "" {
cfg.UserOutbox.Topic = defaults.UserOutbox.Topic
}
if cfg.UserOutbox.ConsumerGroup = strings.TrimSpace(cfg.UserOutbox.ConsumerGroup); cfg.UserOutbox.ConsumerGroup == "" {
cfg.UserOutbox.ConsumerGroup = defaults.UserOutbox.ConsumerGroup
}
if cfg.UserOutbox.TaskConsumerGroup = strings.TrimSpace(cfg.UserOutbox.TaskConsumerGroup); cfg.UserOutbox.TaskConsumerGroup == "" {
cfg.UserOutbox.TaskConsumerGroup = defaults.UserOutbox.TaskConsumerGroup
}
if cfg.UserOutbox.InviteActivityConsumerGroup = strings.TrimSpace(cfg.UserOutbox.InviteActivityConsumerGroup); cfg.UserOutbox.InviteActivityConsumerGroup == "" {
cfg.UserOutbox.InviteActivityConsumerGroup = defaults.UserOutbox.InviteActivityConsumerGroup
}
if cfg.UserOutbox.MessageActionConsumerGroup = strings.TrimSpace(cfg.UserOutbox.MessageActionConsumerGroup); cfg.UserOutbox.MessageActionConsumerGroup == "" {
cfg.UserOutbox.MessageActionConsumerGroup = defaults.UserOutbox.MessageActionConsumerGroup
}
if cfg.UserOutbox.ConsumerMaxReconsumeTimes <= 0 {
cfg.UserOutbox.ConsumerMaxReconsumeTimes = defaults.UserOutbox.ConsumerMaxReconsumeTimes
}
if cfg.MessageActionOutbox.Topic = strings.TrimSpace(cfg.MessageActionOutbox.Topic); cfg.MessageActionOutbox.Topic == "" {
cfg.MessageActionOutbox.Topic = defaults.MessageActionOutbox.Topic
}
if cfg.MessageActionOutbox.ProducerGroup = strings.TrimSpace(cfg.MessageActionOutbox.ProducerGroup); cfg.MessageActionOutbox.ProducerGroup == "" {
cfg.MessageActionOutbox.ProducerGroup = defaults.MessageActionOutbox.ProducerGroup
}
if cfg.MessageActionOutbox.SendTimeout <= 0 {
cfg.MessageActionOutbox.SendTimeout = defaults.MessageActionOutbox.SendTimeout
}
if cfg.MessageActionOutbox.Retry < 0 {
cfg.MessageActionOutbox.Retry = defaults.MessageActionOutbox.Retry
}
if cfg.RoomOutbox.Enabled || cfg.WalletOutbox.Enabled || cfg.UserOutbox.Enabled || cfg.MessageActionOutbox.Enabled {
cfg.Enabled = true
}
if cfg.Enabled {
if len(cfg.NameServers) == 0 && cfg.NameServerDomain == "" {
return RocketMQConfig{}, errors.New("rocketmq name_servers or name_server_domain is required")
}
if (cfg.AccessKey == "") != (cfg.SecretKey == "") {
return RocketMQConfig{}, errors.New("rocketmq access_key and secret_key must be configured together")
}
}
return cfg, nil
}
func normalizeStringSlice(input []string) []string {
out := make([]string, 0, len(input))
for _, value := range input {
if value = strings.TrimSpace(value); value != "" {
out = append(out, value)
}
}
return out
}