226 lines
6.8 KiB
Go
226 lines
6.8 KiB
Go
// Package config defines cron-service runtime configuration.
|
|
package config
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/pkg/configx"
|
|
"hyapp/pkg/logx"
|
|
)
|
|
|
|
const defaultAppCode = "lalu"
|
|
|
|
// Config describes cron-service startup and schedule settings.
|
|
type Config struct {
|
|
// ServiceName is written into logs and health metadata.
|
|
ServiceName string `yaml:"service_name"`
|
|
// NodeID identifies this scheduler instance in run history and task leases.
|
|
NodeID string `yaml:"node_id"`
|
|
// Environment is the runtime environment tag used by structured logs.
|
|
Environment string `yaml:"environment"`
|
|
// GRPCAddr exposes gRPC health and future internal management APIs.
|
|
GRPCAddr string `yaml:"grpc_addr"`
|
|
// HealthHTTPAddr exposes HTTP health for CLB and deploy scripts only.
|
|
HealthHTTPAddr string `yaml:"health_http_addr"`
|
|
// MySQLDSN stores cron run history and schedule-level leases only.
|
|
MySQLDSN string `yaml:"mysql_dsn"`
|
|
// UserServiceAddr is the owner endpoint for user/auth/host batch tasks.
|
|
UserServiceAddr string `yaml:"user_service_addr"`
|
|
// ActivityServiceAddr is the owner endpoint for activity/message batch tasks.
|
|
ActivityServiceAddr string `yaml:"activity_service_addr"`
|
|
// WalletServiceAddr is the owner endpoint for wallet/VIP/settlement tasks.
|
|
WalletServiceAddr string `yaml:"wallet_service_addr"`
|
|
// Tasks contains per-task schedule knobs. Disabled tasks are documented but not started.
|
|
Tasks map[string]TaskConfig `yaml:"tasks"`
|
|
// Log controls stdout structured logging.
|
|
Log logx.Config `yaml:"log"`
|
|
}
|
|
|
|
// TaskConfig keeps scheduler knobs as strings so YAML stays easy to read.
|
|
type TaskConfig struct {
|
|
// Enabled controls whether cron-service starts a loop for this task.
|
|
Enabled bool `yaml:"enabled"`
|
|
// Interval is the delay between successful schedule attempts.
|
|
Interval string `yaml:"interval"`
|
|
// Timeout bounds the owner service RPC call for one batch.
|
|
Timeout string `yaml:"timeout"`
|
|
// LockTTL is the owner service task claim lock budget.
|
|
LockTTL string `yaml:"lock_ttl"`
|
|
// BatchSize is passed to owner service batch RPCs.
|
|
BatchSize int `yaml:"batch_size"`
|
|
// AppCodes scopes the task by tenant; every app_code gets an independent run.
|
|
AppCodes []string `yaml:"app_codes"`
|
|
// PendingPublishMaxAge is used by mic_open_session_compensation for pending_publish sessions.
|
|
PendingPublishMaxAge string `yaml:"pending_publish_max_age"`
|
|
// PublishingSessionMaxAge is used by mic_open_session_compensation for publishing sessions.
|
|
PublishingSessionMaxAge string `yaml:"publishing_session_max_age"`
|
|
}
|
|
|
|
// Default returns local development defaults that follow the 13xxx port rule.
|
|
func Default() Config {
|
|
return Config{
|
|
ServiceName: "cron-service",
|
|
NodeID: "cron-local",
|
|
Environment: "local",
|
|
GRPCAddr: ":13007",
|
|
HealthHTTPAddr: ":13107",
|
|
MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_cron?parseTime=true&charset=utf8mb4&loc=UTC",
|
|
UserServiceAddr: "127.0.0.1:13005",
|
|
ActivityServiceAddr: "127.0.0.1:13006",
|
|
WalletServiceAddr: "127.0.0.1:13004",
|
|
Tasks: defaultTasks(),
|
|
Log: logx.Config{
|
|
Level: "info",
|
|
Format: "json",
|
|
MaxPayloadBytes: 2048,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Load reads a YAML file into Config and normalizes empty fields.
|
|
func Load(path string) (Config, error) {
|
|
cfg := Default()
|
|
if path == "" {
|
|
return cfg, nil
|
|
}
|
|
if err := configx.LoadYAML(path, &cfg); err != nil {
|
|
return Config{}, err
|
|
}
|
|
normalize(&cfg)
|
|
return cfg, nil
|
|
}
|
|
|
|
func normalize(cfg *Config) {
|
|
cfg.ServiceName = strings.TrimSpace(cfg.ServiceName)
|
|
if cfg.ServiceName == "" {
|
|
cfg.ServiceName = "cron-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 = ":13007"
|
|
}
|
|
cfg.HealthHTTPAddr = strings.TrimSpace(cfg.HealthHTTPAddr)
|
|
if cfg.HealthHTTPAddr == "" {
|
|
cfg.HealthHTTPAddr = ":13107"
|
|
}
|
|
cfg.Tasks = normalizeTasks(cfg.Tasks)
|
|
}
|
|
|
|
func defaultTasks() map[string]TaskConfig {
|
|
return map[string]TaskConfig{
|
|
"login_ip_risk": {
|
|
Enabled: true,
|
|
Interval: "5s",
|
|
Timeout: "3s",
|
|
LockTTL: "30s",
|
|
BatchSize: 100,
|
|
AppCodes: []string{defaultAppCode},
|
|
},
|
|
"user_region_rebuild": {
|
|
Enabled: true,
|
|
Interval: "5s",
|
|
Timeout: "5s",
|
|
LockTTL: "30s",
|
|
BatchSize: 500,
|
|
AppCodes: []string{defaultAppCode},
|
|
},
|
|
"message_fanout": {
|
|
Enabled: true,
|
|
Interval: "1s",
|
|
Timeout: "10s",
|
|
LockTTL: "30s",
|
|
BatchSize: 500,
|
|
AppCodes: []string{defaultAppCode},
|
|
},
|
|
"mic_open_session_compensation": {
|
|
Enabled: true,
|
|
Interval: "60s",
|
|
Timeout: "10s",
|
|
LockTTL: "60s",
|
|
BatchSize: 100,
|
|
AppCodes: []string{defaultAppCode},
|
|
PendingPublishMaxAge: "2m",
|
|
PublishingSessionMaxAge: "12h",
|
|
},
|
|
}
|
|
}
|
|
|
|
func normalizeTasks(tasks map[string]TaskConfig) map[string]TaskConfig {
|
|
defaults := defaultTasks()
|
|
if tasks == nil {
|
|
tasks = map[string]TaskConfig{}
|
|
}
|
|
for name, def := range defaults {
|
|
current, ok := tasks[name]
|
|
if !ok {
|
|
tasks[name] = def
|
|
continue
|
|
}
|
|
tasks[name] = mergeTaskConfig(def, current)
|
|
}
|
|
for name, task := range tasks {
|
|
tasks[name] = mergeTaskConfig(TaskConfig{
|
|
Interval: "5s",
|
|
Timeout: "5s",
|
|
LockTTL: "30s",
|
|
BatchSize: 100,
|
|
AppCodes: []string{defaultAppCode},
|
|
}, task)
|
|
}
|
|
return tasks
|
|
}
|
|
|
|
func mergeTaskConfig(def TaskConfig, current TaskConfig) TaskConfig {
|
|
current.Interval = strings.TrimSpace(current.Interval)
|
|
if current.Interval == "" {
|
|
current.Interval = def.Interval
|
|
}
|
|
current.Timeout = strings.TrimSpace(current.Timeout)
|
|
if current.Timeout == "" {
|
|
current.Timeout = def.Timeout
|
|
}
|
|
current.LockTTL = strings.TrimSpace(current.LockTTL)
|
|
if current.LockTTL == "" {
|
|
current.LockTTL = def.LockTTL
|
|
}
|
|
current.PendingPublishMaxAge = strings.TrimSpace(current.PendingPublishMaxAge)
|
|
if current.PendingPublishMaxAge == "" {
|
|
current.PendingPublishMaxAge = def.PendingPublishMaxAge
|
|
}
|
|
current.PublishingSessionMaxAge = strings.TrimSpace(current.PublishingSessionMaxAge)
|
|
if current.PublishingSessionMaxAge == "" {
|
|
current.PublishingSessionMaxAge = def.PublishingSessionMaxAge
|
|
}
|
|
if current.BatchSize <= 0 {
|
|
current.BatchSize = def.BatchSize
|
|
}
|
|
current.AppCodes = normalizeAppCodes(current.AppCodes)
|
|
if len(current.AppCodes) == 0 {
|
|
current.AppCodes = def.AppCodes
|
|
}
|
|
return current
|
|
}
|
|
|
|
func normalizeAppCodes(values []string) []string {
|
|
seen := map[string]bool{}
|
|
result := make([]string, 0, len(values))
|
|
for _, value := range values {
|
|
code := appcode.Normalize(value)
|
|
if code == "" || seen[code] {
|
|
continue
|
|
}
|
|
seen[code] = true
|
|
result = append(result, code)
|
|
}
|
|
return result
|
|
}
|