sync: 同步短信服务 v1.0.4 并脱敏
This commit is contained in:
+68
-11
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -48,41 +49,54 @@ func configFileCandidates() (paths []string, explicit bool) {
|
||||
// 返回的第二个值为实际命中的路径;未命中时路径为空。
|
||||
// 显式指定 SMS_CONFIG_FILE 但读取或解析失败时返回错误,避免静默使用空凭证。
|
||||
func LoadDefaultConfigFromFile() (Config, string, error) {
|
||||
data, path, err := readDefaultConfigFile()
|
||||
if err != nil {
|
||||
return Config{}, "", err
|
||||
}
|
||||
if path == "" {
|
||||
return Config{}, "", nil
|
||||
}
|
||||
var cfg Config
|
||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||
return Config{}, "", fmt.Errorf("解析配置文件 %s 失败: %w", path, err)
|
||||
}
|
||||
return cfg, path, nil
|
||||
}
|
||||
|
||||
// readDefaultConfigFile 按候选路径查找并读取配置文件,返回文件内容与命中路径。
|
||||
// 未命中任何候选文件时返回空内容与空路径(不视为错误);
|
||||
// 显式指定 SMS_CONFIG_FILE 时任何失败都返回错误,避免静默回退。
|
||||
func readDefaultConfigFile() ([]byte, string, error) {
|
||||
paths, explicit := configFileCandidates()
|
||||
for _, path := range paths {
|
||||
info, statErr := os.Stat(path)
|
||||
if statErr != nil {
|
||||
if explicit {
|
||||
return Config{}, "", fmt.Errorf("读取配置文件 %s 失败: %w", path, statErr)
|
||||
return nil, "", fmt.Errorf("读取配置文件 %s 失败: %w", path, statErr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Docker 在挂载源不存在时会自动创建同名目录;必须显式报错,
|
||||
// 否则会静默回退到空凭证,表现为短信发送全部失败。
|
||||
if info.IsDir() {
|
||||
return Config{}, "", fmt.Errorf(
|
||||
return nil, "", fmt.Errorf(
|
||||
"配置文件 %s 是目录而非文件:宿主凭证文件可能不存在,Docker 自动创建了目录。"+
|
||||
"请在服务器创建该文件后重新挂载", path)
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
if explicit {
|
||||
return Config{}, "", fmt.Errorf("读取配置文件 %s 失败: %w", path, err)
|
||||
return nil, "", fmt.Errorf("读取配置文件 %s 失败: %w", path, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
var cfg Config
|
||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||
return Config{}, "", fmt.Errorf("解析配置文件 %s 失败: %w", path, err)
|
||||
}
|
||||
return cfg, path, nil
|
||||
return data, path, nil
|
||||
}
|
||||
if explicit {
|
||||
return Config{}, "", fmt.Errorf("指定的配置文件不存在: %s", paths[0])
|
||||
return nil, "", fmt.Errorf("指定的配置文件不存在: %s", paths[0])
|
||||
}
|
||||
return Config{}, "", nil
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
// envOverrides 定义环境变量到配置字段的映射,环境变量优先于配置文件。
|
||||
var envOverrides = []struct {
|
||||
name string
|
||||
@@ -122,3 +136,46 @@ func LoadDefaultConfig() (Config, ConfigSource, error) {
|
||||
}
|
||||
return cfg, ConfigSource{File: path, Env: envApplied}, nil
|
||||
}
|
||||
|
||||
// SceneDbConfig 场景模板配置库(表 t_sms_template_config)连接参数。
|
||||
// DSN 为空表示未启用场景库能力:Send 收到带 scene 的请求时返回 ErrSceneNotConfigured。
|
||||
type SceneDbConfig struct {
|
||||
DSN string `yaml:"sceneDbDsn"`
|
||||
CacheTTL string `yaml:"sceneDbCacheTtl"`
|
||||
}
|
||||
|
||||
// DefaultSceneDbCacheTTL 场景配置缓存默认时长。
|
||||
const DefaultSceneDbCacheTTL = 60 * time.Second
|
||||
|
||||
// TTL 返回解析后的缓存时长;非法或非正值回退默认值。
|
||||
func (c SceneDbConfig) TTL() time.Duration {
|
||||
if v, err := time.ParseDuration(strings.TrimSpace(c.CacheTTL)); err == nil && v > 0 {
|
||||
return v
|
||||
}
|
||||
return DefaultSceneDbCacheTTL
|
||||
}
|
||||
|
||||
// LoadSceneDbConfig 从默认配置文件读取场景库参数(与凭证同一份 config.yaml),环境变量可覆盖。
|
||||
// 未命中配置文件不报错(场景库能力可选);解析失败或显式指定的文件不存在才返回错误。
|
||||
func LoadSceneDbConfig() (SceneDbConfig, ConfigSource, error) {
|
||||
data, path, err := readDefaultConfigFile()
|
||||
if err != nil {
|
||||
return SceneDbConfig{}, ConfigSource{}, err
|
||||
}
|
||||
sc := SceneDbConfig{}
|
||||
if path != "" {
|
||||
if err := yaml.Unmarshal(data, &sc); err != nil {
|
||||
return SceneDbConfig{}, ConfigSource{}, fmt.Errorf("解析配置文件 %s 失败: %w", path, err)
|
||||
}
|
||||
}
|
||||
envs := make([]string, 0, 2)
|
||||
if v := strings.TrimSpace(os.Getenv("SMS_DB_DSN")); v != "" {
|
||||
sc.DSN = v
|
||||
envs = append(envs, "SMS_DB_DSN")
|
||||
}
|
||||
if v := strings.TrimSpace(os.Getenv("SMS_DB_CONFIG_CACHE_TTL")); v != "" {
|
||||
sc.CacheTTL = v
|
||||
envs = append(envs, "SMS_DB_CONFIG_CACHE_TTL")
|
||||
}
|
||||
return sc, ConfigSource{File: path, Env: envs}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user