backend/pkg/notification/config/config.go

207 lines
4.4 KiB
Go

package config
import (
"errors"
"fmt"
"time"
)
type SMTPConfig struct {
Enable bool
Sort int
GoroutinePoolNum int
Host string
Port int
Username string
Password string
}
// Validate 驗證 SMTP 配置
func (c *SMTPConfig) Validate() error {
if !c.Enable {
return nil // 未啟用則不驗證
}
if c.Host == "" {
return errors.New("smtp host is required")
}
if c.Port <= 0 || c.Port > 65535 {
return fmt.Errorf("smtp port must be between 1 and 65535, got %d", c.Port)
}
if c.Username == "" {
return errors.New("smtp username is required")
}
if c.Password == "" {
return errors.New("smtp password is required")
}
if c.Sort < 0 {
return fmt.Errorf("smtp sort must be >= 0, got %d", c.Sort)
}
return nil
}
type AmazonSesSettings struct {
Enable bool
Sort int
PoolSize int
Region string
Sender string
Charset string
AccessKey string
SecretKey string
Token string
}
// Validate 驗證 AWS SES 配置
func (c *AmazonSesSettings) Validate() error {
if !c.Enable {
return nil // 未啟用則不驗證
}
if c.Region == "" {
return errors.New("aws ses region is required")
}
if c.Sender == "" {
return errors.New("aws ses sender is required")
}
if c.AccessKey == "" {
return errors.New("aws ses access key is required")
}
if c.SecretKey == "" {
return errors.New("aws ses secret key is required")
}
if c.Sort < 0 {
return fmt.Errorf("aws ses sort must be >= 0, got %d", c.Sort)
}
if c.PoolSize < 0 {
return fmt.Errorf("aws ses pool size must be >= 0, got %d", c.PoolSize)
}
return nil
}
type MitakeSMSSender struct {
Enable bool
Sort int
PoolSize int
User string
Password string
}
// Validate 驗證 Mitake SMS 配置
func (c *MitakeSMSSender) Validate() error {
if !c.Enable {
return nil // 未啟用則不驗證
}
if c.User == "" {
return errors.New("mitake user is required")
}
if c.Password == "" {
return errors.New("mitake password is required")
}
if c.Sort < 0 {
return fmt.Errorf("mitake sort must be >= 0, got %d", c.Sort)
}
if c.PoolSize < 0 {
return fmt.Errorf("mitake pool size must be >= 0, got %d", c.PoolSize)
}
return nil
}
// DeliveryConfig 傳送重試配置
type DeliveryConfig struct {
MaxRetries int `json:"max_retries"` // 最大重試次數
InitialDelay time.Duration `json:"initial_delay"` // 初始重試延遲 (100ms)
BackoffFactor float64 `json:"backoff_factor"` // 指數退避因子 (2.0)
MaxDelay time.Duration `json:"max_delay"` // 最大延遲時間
Timeout time.Duration `json:"timeout"` // 單次發送超時時間
EnableHistory bool `json:"enable_history"` // 是否啟用歷史記錄
}
// Validate 驗證 DeliveryConfig 配置
func (c *DeliveryConfig) Validate() error {
if c.MaxRetries < 0 {
return fmt.Errorf("max_retries must be >= 0, got %d", c.MaxRetries)
}
if c.MaxRetries > 10 {
return fmt.Errorf("max_retries should not exceed 10, got %d", c.MaxRetries)
}
if c.InitialDelay < 0 {
return fmt.Errorf("initial_delay must be >= 0, got %v", c.InitialDelay)
}
if c.InitialDelay > 10*time.Second {
return fmt.Errorf("initial_delay is too large (> 10s), got %v", c.InitialDelay)
}
if c.BackoffFactor < 1.0 {
return fmt.Errorf("backoff_factor must be >= 1.0, got %v", c.BackoffFactor)
}
if c.BackoffFactor > 10.0 {
return fmt.Errorf("backoff_factor is too large (> 10.0), got %v", c.BackoffFactor)
}
if c.MaxDelay < 0 {
return fmt.Errorf("max_delay must be >= 0, got %v", c.MaxDelay)
}
if c.MaxDelay > 5*time.Minute {
return fmt.Errorf("max_delay is too large (> 5m), got %v", c.MaxDelay)
}
if c.Timeout <= 0 {
return fmt.Errorf("timeout must be > 0, got %v", c.Timeout)
}
if c.Timeout > 5*time.Minute {
return fmt.Errorf("timeout is too large (> 5m), got %v", c.Timeout)
}
// 檢查 InitialDelay 和 MaxDelay 的關係
if c.InitialDelay > c.MaxDelay && c.MaxDelay > 0 {
return fmt.Errorf("initial_delay (%v) should not exceed max_delay (%v)", c.InitialDelay, c.MaxDelay)
}
return nil
}
// SetDefaults 設置默認值
func (c *DeliveryConfig) SetDefaults() {
if c.MaxRetries == 0 {
c.MaxRetries = 3
}
if c.InitialDelay == 0 {
c.InitialDelay = 100 * time.Millisecond
}
if c.BackoffFactor == 0 {
c.BackoffFactor = 2.0
}
if c.MaxDelay == 0 {
c.MaxDelay = 30 * time.Second
}
if c.Timeout == 0 {
c.Timeout = 30 * time.Second
}
}