Add admin config page and runtime-tunable upload/rate-limit settings
This commit is contained in:
125
internal/config/service.go
Normal file
125
internal/config/service.go
Normal file
@@ -0,0 +1,125 @@
|
||||
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) 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)
|
||||
}
|
||||
Reference in New Issue
Block a user