Конвенция для обработки ошибок + рефакторинг кода
This commit is contained in:
+18
-14
@@ -205,18 +205,22 @@ func Load(path string) (*Config, error) {
|
||||
// включённых секций не пусты. Длительности уже провалидированы при разборе
|
||||
// TOML (UnmarshalText). Лог об ошибке пишет граница (cmd/jellybit), не загрузчик.
|
||||
func (c *Config) validate() error {
|
||||
// Собираем все проблемы разом (errors.Join), чтобы оператор увидел все
|
||||
// огрехи отрендеренного файла за один проход, а не правил их по одной.
|
||||
var errs []error
|
||||
|
||||
// Обязательные поля ядра.
|
||||
if c.QBittorrent.URL == "" {
|
||||
return errors.New("qbittorrent.url is empty")
|
||||
errs = append(errs, errors.New("qbittorrent.url is empty"))
|
||||
}
|
||||
if c.HTTP.Listen == "" {
|
||||
return errors.New("http.listen is empty")
|
||||
errs = append(errs, errors.New("http.listen is empty"))
|
||||
}
|
||||
if c.Storage.DBPath == "" {
|
||||
return errors.New("storage.db_path is empty")
|
||||
errs = append(errs, errors.New("storage.db_path is empty"))
|
||||
}
|
||||
if c.LLM.Type != "openai-compat" {
|
||||
return fmt.Errorf("unsupported llm.type %q (supported: openai-compat)", c.LLM.Type)
|
||||
errs = append(errs, fmt.Errorf("unsupported llm.type %q (supported: openai-compat)", c.LLM.Type))
|
||||
}
|
||||
|
||||
// Медиа-пути песочницы: абсолютные, без traversal, существующие каталоги.
|
||||
@@ -226,45 +230,45 @@ func (c *Config) validate() error {
|
||||
{"paths.series", c.Paths.Series},
|
||||
} {
|
||||
if err := validateMediaDir(p.name, p.path); err != nil {
|
||||
return err
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Диапазоны.
|
||||
if t := c.Recognition.AutoConfidenceThreshold; t < 0 || t > 1 {
|
||||
return fmt.Errorf("recognition.auto_confidence_threshold %.3f is out of range [0, 1]", t)
|
||||
errs = append(errs, fmt.Errorf("recognition.auto_confidence_threshold %.3f is out of range [0, 1]", t))
|
||||
}
|
||||
if c.LLM.MaxRetries < 0 {
|
||||
return fmt.Errorf("llm.max_retries %d must be >= 0", c.LLM.MaxRetries)
|
||||
errs = append(errs, fmt.Errorf("llm.max_retries %d must be >= 0", c.LLM.MaxRetries))
|
||||
}
|
||||
|
||||
// Обязательные секреты включённых секций (ловит криво отрендеренный деплоем
|
||||
// файл). qBittorrent — ядро, пароль нужен всегда.
|
||||
if c.QBittorrent.Password == "" {
|
||||
return errors.New("qbittorrent.password is empty (required secret)")
|
||||
errs = append(errs, errors.New("qbittorrent.password is empty (required secret)"))
|
||||
}
|
||||
// llm.api_key намеренно не обязателен: keyless-local LLM (LM Studio с
|
||||
// заданным base_url, но без ключа) — валидный документированный дефолт.
|
||||
|
||||
// Консистентность опциональных секций: enabled ⇒ заданы нужные поля/секреты.
|
||||
if c.Metadata.TMDB.Enabled && c.Metadata.TMDB.APIKey == "" {
|
||||
return errors.New("metadata.tmdb.enabled but metadata.tmdb.api_key is empty")
|
||||
errs = append(errs, errors.New("metadata.tmdb.enabled but metadata.tmdb.api_key is empty"))
|
||||
}
|
||||
if c.Metadata.TVDB.Enabled && c.Metadata.TVDB.APIKey == "" {
|
||||
return errors.New("metadata.tvdb.enabled but metadata.tvdb.api_key is empty")
|
||||
errs = append(errs, errors.New("metadata.tvdb.enabled but metadata.tvdb.api_key is empty"))
|
||||
}
|
||||
if c.Jellyfin.Enabled {
|
||||
if c.Jellyfin.URL == "" {
|
||||
return errors.New("jellyfin.enabled but jellyfin.url is empty")
|
||||
errs = append(errs, errors.New("jellyfin.enabled but jellyfin.url is empty"))
|
||||
}
|
||||
if c.Jellyfin.APIKey == "" {
|
||||
return errors.New("jellyfin.enabled but jellyfin.api_key is empty (required secret)")
|
||||
errs = append(errs, errors.New("jellyfin.enabled but jellyfin.api_key is empty (required secret)"))
|
||||
}
|
||||
}
|
||||
if c.Telegram.Enabled && c.Telegram.Token == "" {
|
||||
return errors.New("telegram.enabled but telegram.token is empty (required secret)")
|
||||
errs = append(errs, errors.New("telegram.enabled but telegram.token is empty (required secret)"))
|
||||
}
|
||||
return nil
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// validateMediaDir проверяет путь медиа-песочницы: непустой, абсолютный, без
|
||||
|
||||
Reference in New Issue
Block a user