release: 1.5.0: Send-log retention configurable in panel Settings

Send-log retention is configurable from panel **Settings** (global administrator); `SEND_LOG_RETENTION_DAYS` seeds the initial default only.
Added:
  - Panel **Settings** (global administrator): **Send log retention (days)** —
Changed:
  - Deliveries list and delivery detail pages show the configured retention

Full detail: CHANGELOG.md (1.5.0).
This commit is contained in:
mix
2026-09-22 15:24:52 +03:00
parent 656c4d4d7f
commit dca7d99c1b
24 changed files with 593 additions and 135 deletions
+71
View File
@@ -4,8 +4,79 @@ import (
"database/sql"
"errors"
"fmt"
"strconv"
)
const (
// SendLogRetentionDaysKey is the settings table key for delivery-journal
// retention (architecture.md § Persistence).
SendLogRetentionDaysKey = "send_log_retention_days"
SendLogRetentionDaysMin = 7
SendLogRetentionDaysMax = 365
// SendLogRetentionDaysDefault matches SEND_LOG_RETENTION_DAYS when unset.
SendLogRetentionDaysDefault = 90
)
// ErrSendLogRetentionDaysOutOfRange is returned when retention is outside the
// allowed panel range.
var ErrSendLogRetentionDaysOutOfRange = errors.New("send log retention days out of range")
// ValidateSendLogRetentionDays checks the panel-allowed retention window.
func ValidateSendLogRetentionDays(days int) error {
if days < SendLogRetentionDaysMin || days > SendLogRetentionDaysMax {
return fmt.Errorf("%w: must be between %d and %d days", ErrSendLogRetentionDaysOutOfRange, SendLogRetentionDaysMin, SendLogRetentionDaysMax)
}
return nil
}
func sendLogRetentionFallback(envDefault int) int {
if envDefault > 0 {
if err := ValidateSendLogRetentionDays(envDefault); err == nil {
return envDefault
}
}
return SendLogRetentionDaysDefault
}
// GetSendLogRetentionDays returns the effective retention window. When the
// setting is missing or invalid, envDefault is used (guide § Environment
// variables: SEND_LOG_RETENTION_DAYS).
func (s *Store) GetSendLogRetentionDays(envDefault int) (int, error) {
raw, err := s.GetSetting(SendLogRetentionDaysKey)
if err != nil {
return 0, err
}
if raw == "" {
return sendLogRetentionFallback(envDefault), nil
}
days, err := strconv.Atoi(raw)
if err != nil || ValidateSendLogRetentionDays(days) != nil {
return sendLogRetentionFallback(envDefault), nil
}
return days, nil
}
// SetSendLogRetentionDays persists the panel-configured retention window.
func (s *Store) SetSendLogRetentionDays(days int) error {
if err := ValidateSendLogRetentionDays(days); err != nil {
return err
}
return s.SetSetting(SendLogRetentionDaysKey, strconv.Itoa(days))
}
// EnsureSendLogRetentionDays seeds the setting from envDefault when it has
// never been written (first panel start after upgrade).
func (s *Store) EnsureSendLogRetentionDays(envDefault int) error {
raw, err := s.GetSetting(SendLogRetentionDaysKey)
if err != nil {
return err
}
if raw != "" {
return nil
}
return s.SetSendLogRetentionDays(sendLogRetentionFallback(envDefault))
}
// GetSetting returns a settings value or empty string when missing.
func (s *Store) GetSetting(key string) (string, error) {
var value string