Files
ReSendit/internal/config/service.go
2026-03-26 13:54:29 +01:00

135 lines
2.3 KiB
Go

package config
import (
"errors"
"strconv"
"sync"
"time"
"gorm.io/gorm"
)
type Service struct {
repo *Repository
// Small in-memory cache to avoid hitting the DB on every request.
// Updated on SetString; lazy-filled on first Get.
mu sync.RWMutex
cache map[string]string
}
func NewService(r *Repository) *Service {
return &Service{repo: r, cache: make(map[string]string)}
}
func (s *Service) EnsureDefaults() error {
for k, v := range DefaultKeyValues() {
if err := s.repo.CreateIfMissing(k, v); err != nil {
return err
}
}
return nil
}
func (s *Service) List() ([]ConfigEntry, error) {
entries, err := s.repo.List()
if err != nil {
return nil, err
}
// refresh cache snapshot
s.mu.Lock()
for _, e := range entries {
s.cache[e.Key] = e.Value
}
s.mu.Unlock()
return entries, nil
}
func (s *Service) SetString(key, value string) error {
if err := s.repo.Upsert(key, value); err != nil {
return err
}
s.mu.Lock()
s.cache[key] = value
s.mu.Unlock()
return nil
}
func (s *Service) GetStringDefault(key, def string) string {
s.mu.RLock()
v, ok := s.cache[key]
s.mu.RUnlock()
if ok {
if v == "" {
return def
}
return v
}
e, err := s.repo.Get(key)
if err != nil {
return def
}
s.mu.Lock()
s.cache[key] = e.Value
s.mu.Unlock()
if e.Value == "" {
return def
}
return e.Value
}
func (s *Service) GetIntDefault(key string, def int) int {
v := s.GetStringDefault(key, "")
if v == "" {
return def
}
n, err := strconv.Atoi(v)
if err != nil {
return def
}
return n
}
func (s *Service) GetInt64Default(key string, def int64) int64 {
v := s.GetStringDefault(key, "")
if v == "" {
return def
}
n, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return def
}
return n
}
func (s *Service) GetBoolDefault(key string, def bool) bool {
v := s.GetStringDefault(key, "")
if v == "" {
return def
}
b, err := strconv.ParseBool(v)
if err != nil {
return def
}
return b
}
func (s *Service) GetDurationSecondsDefault(key string, def time.Duration) time.Duration {
v := s.GetStringDefault(key, "")
if v == "" {
return def
}
n, err := strconv.Atoi(v)
if err != nil {
return def
}
return time.Duration(n) * time.Second
}
func IsNotFound(err error) bool {
return errors.Is(err, gorm.ErrRecordNotFound)
}