mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 06:03:51 +03:00
2dc167cbb9
The following message is displayed when upgrading to Forgejo: [W] Table system_setting Column version db default is , struct default is 1 The same message also shows when upgrading from Gitea 1.21 to Gitea 1.22. It is fine for the version field to default to zero or NULL instead of one.
152 lines
3.6 KiB
Go
152 lines
3.6 KiB
Go
// 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
|
|
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{}
|
|
}
|