| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // Copyright 2021 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package system
-
- import (
- "context"
- "math"
- "sync"
- "time"
-
- "code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting/config"
- "code.gitea.io/gitea/modules/timeutil"
-
- "xorm.io/builder"
- )
-
- type Setting struct {
- ID int64 `xorm:"pk autoincr"`
- SettingKey string `xorm:"varchar(255) unique"` // key should be lowercase
- SettingValue string `xorm:"text"`
- Version int `xorm:"version"`
- Created timeutil.TimeStamp `xorm:"created"`
- Updated timeutil.TimeStamp `xorm:"updated"`
- }
-
- // TableName sets the table name for the settings struct
- func (s *Setting) TableName() string {
- return "system_setting"
- }
-
- func init() {
- db.RegisterModel(new(Setting))
- }
-
- const keyRevision = "revision"
-
- func GetRevision(ctx context.Context) int {
- revision, exist, err := db.Get[Setting](ctx, builder.Eq{"setting_key": keyRevision})
- if err != nil {
- return 0
- } else if !exist {
- err = db.Insert(ctx, &Setting{SettingKey: keyRevision, Version: 1})
- if err != nil {
- return 0
- }
- return 1
- }
- if revision.Version <= 0 || revision.Version >= math.MaxInt-1 {
- _, err = db.Exec(ctx, "UPDATE system_setting SET version=1 WHERE setting_key=?", keyRevision)
- if err != nil {
- return 0
- }
- return 1
- }
- return revision.Version
- }
-
- func GetAllSettings(ctx context.Context) (revision int, res map[string]string, err error) {
- _ = GetRevision(ctx) // prepare the "revision" key ahead
- var settings []*Setting
- if err := db.GetEngine(ctx).
- Find(&settings); err != nil {
- return 0, nil, err
- }
- res = make(map[string]string)
- for _, s := range settings {
- if s.SettingKey == keyRevision {
- revision = s.Version
- }
- res[s.SettingKey] = s.SettingValue
- }
- return revision, res, nil
- }
-
- func SetSettings(ctx context.Context, settings map[string]string) error {
- _ = GetRevision(ctx) // prepare the "revision" key ahead
- return db.WithTx(ctx, func(ctx context.Context) error {
- e := db.GetEngine(ctx)
- _, err := db.Exec(ctx, "UPDATE system_setting SET version=version+1 WHERE setting_key=?", keyRevision)
- if err != nil {
- return err
- }
- for k, v := range settings {
- res, err := e.Exec("UPDATE system_setting SET version=version+1, setting_value=? WHERE setting_key=?", v, k)
- if err != nil {
- return err
- }
- rows, _ := res.RowsAffected()
- if rows == 0 { // if no existing row, insert a new row
- if _, err = e.Insert(&Setting{SettingKey: k, SettingValue: v}); err != nil {
- return err
- }
- }
- }
- return nil
- })
- }
-
- type dbConfigCachedGetter struct {
- mu sync.RWMutex
-
- cacheTime time.Time
- revision int
- settings map[string]string
- }
-
- var _ config.DynKeyGetter = (*dbConfigCachedGetter)(nil)
-
- func (d *dbConfigCachedGetter) GetValue(ctx context.Context, key string) (v string, has bool) {
- d.mu.RLock()
- defer d.mu.RUnlock()
- v, has = d.settings[key]
- return v, has
- }
-
- func (d *dbConfigCachedGetter) GetRevision(ctx context.Context) int {
- d.mu.RLock()
- cachedDuration := time.Since(d.cacheTime)
- cachedRevision := d.revision
- d.mu.RUnlock()
-
- if cachedDuration < time.Second {
- return cachedRevision
- }
-
- d.mu.Lock()
- defer d.mu.Unlock()
- if GetRevision(ctx) != d.revision {
- rev, set, err := GetAllSettings(ctx)
- if err != nil {
- log.Error("Unable to get all settings: %v", err)
- } else {
- d.revision = rev
- d.settings = set
- }
- }
- d.cacheTime = time.Now()
- return d.revision
- }
-
- func (d *dbConfigCachedGetter) InvalidateCache() {
- d.mu.Lock()
- d.cacheTime = time.Time{}
- d.mu.Unlock()
- }
-
- func NewDatabaseDynKeyGetter() config.DynKeyGetter {
- return &dbConfigCachedGetter{}
- }
|