refactor: common util package, ESL/AMI/security fixes, Prometheus metrics
Backend stability and security improvements: * internal/util/ — common RandomHex helper, removed 3 duplicates * ESL: deduplicated readMessage (locked/unlocked), net.JoinHostPort for IPv6 * AMI: synchronous reconnect() in readEventsLoop, net.JoinHostPort for IPv6 * Auth: /api/auth/refresh accepts Authorization header only (no ?token=) * decodeJSON: http.MaxBytesReader(1<<20) body limit * Trunks: gatewayParams() uses configured ESL.GatewayPrefix * Config: jwt_secret_env env-var fallback * FSCollector: time.After → time.NewTimer with defer Stop * Monitoring: Prometheus counters (route_requests, nodes_total/healthy, uptime) * go fmt pass across all internal/ packages
This commit is contained in:
+36
-25
@@ -27,9 +27,9 @@ type ScoringWeights struct {
|
||||
|
||||
// ScoringConfig — пороги и веса для scoring engine.
|
||||
type ScoringConfig struct {
|
||||
IdleCPUMin float64 `json:"idle_cpu_min"`
|
||||
CallFailureRateLethal float64 `json:"call_failure_rate_lethal"`
|
||||
Weights ScoringWeights `json:"weights"`
|
||||
IdleCPUMin float64 `json:"idle_cpu_min"`
|
||||
CallFailureRateLethal float64 `json:"call_failure_rate_lethal"`
|
||||
Weights ScoringWeights `json:"weights"`
|
||||
}
|
||||
|
||||
// TLSConfig — настройки HTTPS.
|
||||
@@ -54,11 +54,11 @@ type LogConfig struct {
|
||||
|
||||
// ESLConfig — настройки подключения к FreeSWITCH ESL.
|
||||
type ESLConfig struct {
|
||||
Host string `json:"host"` // если пустой — ESL не запускается
|
||||
Port int `json:"port"` // порт ESL (по умолчанию 8021)
|
||||
Host string `json:"host"` // если пустой — ESL не запускается
|
||||
Port int `json:"port"` // порт ESL (по умолчанию 8021)
|
||||
Password string `json:"password"`
|
||||
PasswordEnv string `json:"password_env"` // имя переменной окружения с паролем
|
||||
SofiaProfile string `json:"sofia_profile"` // профиль Sofia (external/internal)
|
||||
PasswordEnv string `json:"password_env"` // имя переменной окружения с паролем
|
||||
SofiaProfile string `json:"sofia_profile"` // профиль Sofia (external/internal)
|
||||
GatewayPrefix string `json:"gateway_prefix"` // префикс gateway (pulse)
|
||||
}
|
||||
|
||||
@@ -72,20 +72,31 @@ func (e *ESLConfig) GetPassword() string {
|
||||
return e.Password
|
||||
}
|
||||
|
||||
// GetJWTSecret возвращает JWT-секрет: из переменной окружения, если задан jwt_secret_env, иначе из поля jwt_secret.
|
||||
func (c *Config) GetJWTSecret() string {
|
||||
if c.JWTSecretEnv != "" {
|
||||
if val := os.Getenv(c.JWTSecretEnv); val != "" {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return c.JWTSecret
|
||||
}
|
||||
|
||||
// Config — корневая конфигурация приложения (config.json).
|
||||
type Config struct {
|
||||
NatsURL string `json:"nats_url"`
|
||||
NatsUser string `json:"nats_user"`
|
||||
NatsPassword string `json:"nats_password"`
|
||||
ListenAddr string `json:"listen_addr"`
|
||||
JWTSecret string `json:"jwt_secret"`
|
||||
MonitoringAPIKey string `json:"monitoring_api_key"`
|
||||
StaleThresholdSec int `json:"stale_threshold_sec"`
|
||||
Scoring ScoringConfig `json:"scoring"`
|
||||
TLS TLSConfig `json:"tls"`
|
||||
RateLimit RateLimitConfig `json:"rate_limit"`
|
||||
Log LogConfig `json:"log"`
|
||||
ESL ESLConfig `json:"esl"`
|
||||
NatsURL string `json:"nats_url"`
|
||||
NatsUser string `json:"nats_user"`
|
||||
NatsPassword string `json:"nats_password"`
|
||||
ListenAddr string `json:"listen_addr"`
|
||||
JWTSecret string `json:"jwt_secret"`
|
||||
JWTSecretEnv string `json:"jwt_secret_env"` // имя переменной окружения с JWT-секретом
|
||||
MonitoringAPIKey string `json:"monitoring_api_key"`
|
||||
StaleThresholdSec int `json:"stale_threshold_sec"`
|
||||
Scoring ScoringConfig `json:"scoring"`
|
||||
TLS TLSConfig `json:"tls"`
|
||||
RateLimit RateLimitConfig `json:"rate_limit"`
|
||||
Log LogConfig `json:"log"`
|
||||
ESL ESLConfig `json:"esl"`
|
||||
}
|
||||
|
||||
// Validate проверяет корректность всех полей конфига.
|
||||
@@ -168,8 +179,8 @@ func (c *Config) Validate() error {
|
||||
|
||||
// Manager управляет чтением и атомарной записью JSON-конфигов.
|
||||
type Manager struct {
|
||||
mu sync.RWMutex
|
||||
dir string // путь к data/
|
||||
mu sync.RWMutex
|
||||
dir string // путь к data/
|
||||
}
|
||||
|
||||
// NewManager создаёт новый менеджер конфигов из директории dataDir.
|
||||
@@ -302,9 +313,9 @@ func (m *Manager) saveUsersLocked(users []models.User) error {
|
||||
|
||||
// --- Приватные методы ---
|
||||
|
||||
func (m *Manager) configPath() string { return filepath.Join(m.dir, "config.json") }
|
||||
func (m *Manager) trunksPath() string { return filepath.Join(m.dir, "trunks.json") }
|
||||
func (m *Manager) usersPath() string { return filepath.Join(m.dir, "users.json") }
|
||||
func (m *Manager) configPath() string { return filepath.Join(m.dir, "config.json") }
|
||||
func (m *Manager) trunksPath() string { return filepath.Join(m.dir, "trunks.json") }
|
||||
func (m *Manager) usersPath() string { return filepath.Join(m.dir, "users.json") }
|
||||
|
||||
// saveFile атомарно сохраняет данные в файл: tmp → rename.
|
||||
// Вызывающий держит write lock.
|
||||
@@ -355,7 +366,7 @@ func (m *Manager) createDefaultConfig() error {
|
||||
MonitoringAPIKey: apiKey,
|
||||
StaleThresholdSec: 20,
|
||||
Scoring: ScoringConfig{
|
||||
IdleCPUMin: 5.0,
|
||||
IdleCPUMin: 5.0,
|
||||
CallFailureRateLethal: 15.0,
|
||||
Weights: ScoringWeights{
|
||||
CallScore: 0.40,
|
||||
|
||||
Reference in New Issue
Block a user