Avoid warning for system setting when start up (#23054) (#23116)

Backport #23054

Partially fix #23050

After #22294 merged, it always has a warning log like `cannot get
context cache` when starting up. This should not affect any real life
but it's annoying. This PR will fix the problem. That means when
starting up, getting the system settings will not try from the cache but
will read from the database directly.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
Yarden Shoham 2023-02-24 23:46:11 +02:00 committed by GitHub
parent 80c1264f4b
commit 7c3196ceac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 43 additions and 34 deletions

View File

@ -153,7 +153,7 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
return DefaultAvatarLink() return DefaultAvatarLink()
} }
enableFederatedAvatar := system_model.GetSettingBool(ctx, system_model.KeyPictureEnableFederatedAvatar) enableFederatedAvatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureEnableFederatedAvatar)
var err error var err error
if enableFederatedAvatar && system_model.LibravatarService != nil { if enableFederatedAvatar && system_model.LibravatarService != nil {
@ -174,7 +174,7 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
return urlStr return urlStr
} }
disableGravatar := system_model.GetSettingBool(ctx, system_model.KeyPictureDisableGravatar) disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar)
if !disableGravatar { if !disableGravatar {
// copy GravatarSourceURL, because we will modify its Path. // copy GravatarSourceURL, because we will modify its Path.
avatarURLCopy := *system_model.GravatarSourceURL avatarURLCopy := *system_model.GravatarSourceURL

View File

@ -28,7 +28,7 @@ func enableGravatar(t *testing.T) {
err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "false") err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "false")
assert.NoError(t, err) assert.NoError(t, err)
setting.GravatarSource = gravatarSource setting.GravatarSource = gravatarSource
err = system_model.Init() err = system_model.Init(db.DefaultContext)
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -39,9 +39,9 @@ import (
var ItemsPerPage = 40 var ItemsPerPage = 40
// Init initialize model // Init initialize model
func Init() error { func Init(ctx context.Context) error {
unit.LoadUnitConfig() unit.LoadUnitConfig()
return system_model.Init() return system_model.Init(ctx)
} }
// DeleteRepository deletes a repository for a user or organization. // DeleteRepository deletes a repository for a user or organization.

View File

@ -79,8 +79,8 @@ func IsErrDataExpired(err error) bool {
return ok return ok
} }
// GetSettingNoCache returns specific setting without using the cache // GetSetting returns specific setting without using the cache
func GetSettingNoCache(ctx context.Context, key string) (*Setting, error) { func GetSetting(ctx context.Context, key string) (*Setting, error) {
v, err := GetSettings(ctx, []string{key}) v, err := GetSettings(ctx, []string{key})
if err != nil { if err != nil {
return nil, err return nil, err
@ -93,11 +93,11 @@ func GetSettingNoCache(ctx context.Context, key string) (*Setting, error) {
const contextCacheKey = "system_setting" const contextCacheKey = "system_setting"
// GetSetting returns the setting value via the key // GetSettingWithCache returns the setting value via the key
func GetSetting(ctx context.Context, key string) (string, error) { func GetSettingWithCache(ctx context.Context, key string) (string, error) {
return cache.GetWithContextCache(ctx, contextCacheKey, key, func() (string, error) { return cache.GetWithContextCache(ctx, contextCacheKey, key, func() (string, error) {
return cache.GetString(genSettingCacheKey(key), func() (string, error) { return cache.GetString(genSettingCacheKey(key), func() (string, error) {
res, err := GetSettingNoCache(ctx, key) res, err := GetSetting(ctx, key)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -110,6 +110,15 @@ func GetSetting(ctx context.Context, key string) (string, error) {
// none existing keys and errors are ignored and result in false // none existing keys and errors are ignored and result in false
func GetSettingBool(ctx context.Context, key string) bool { func GetSettingBool(ctx context.Context, key string) bool {
s, _ := GetSetting(ctx, key) s, _ := GetSetting(ctx, key)
if s == nil {
return false
}
v, _ := strconv.ParseBool(s.SettingValue)
return v
}
func GetSettingWithCacheBool(ctx context.Context, key string) bool {
s, _ := GetSettingWithCache(ctx, key)
v, _ := strconv.ParseBool(s) v, _ := strconv.ParseBool(s)
return v return v
} }
@ -120,7 +129,7 @@ func GetSettings(ctx context.Context, keys []string) (map[string]*Setting, error
keys[i] = strings.ToLower(keys[i]) keys[i] = strings.ToLower(keys[i])
} }
settings := make([]*Setting, 0, len(keys)) settings := make([]*Setting, 0, len(keys))
if err := db.GetEngine(db.DefaultContext). if err := db.GetEngine(ctx).
Where(builder.In("setting_key", keys)). Where(builder.In("setting_key", keys)).
Find(&settings); err != nil { Find(&settings); err != nil {
return nil, err return nil, err
@ -151,9 +160,9 @@ func (settings AllSettings) GetVersion(key string) int {
} }
// GetAllSettings returns all settings from user // GetAllSettings returns all settings from user
func GetAllSettings() (AllSettings, error) { func GetAllSettings(ctx context.Context) (AllSettings, error) {
settings := make([]*Setting, 0, 5) settings := make([]*Setting, 0, 5)
if err := db.GetEngine(db.DefaultContext). if err := db.GetEngine(ctx).
Find(&settings); err != nil { Find(&settings); err != nil {
return nil, err return nil, err
} }
@ -168,12 +177,12 @@ func GetAllSettings() (AllSettings, error) {
func DeleteSetting(ctx context.Context, setting *Setting) error { func DeleteSetting(ctx context.Context, setting *Setting) error {
cache.RemoveContextData(ctx, contextCacheKey, setting.SettingKey) cache.RemoveContextData(ctx, contextCacheKey, setting.SettingKey)
cache.Remove(genSettingCacheKey(setting.SettingKey)) cache.Remove(genSettingCacheKey(setting.SettingKey))
_, err := db.GetEngine(db.DefaultContext).Delete(setting) _, err := db.GetEngine(ctx).Delete(setting)
return err return err
} }
func SetSettingNoVersion(ctx context.Context, key, value string) error { func SetSettingNoVersion(ctx context.Context, key, value string) error {
s, err := GetSettingNoCache(ctx, key) s, err := GetSetting(ctx, key)
if IsErrSettingIsNotExist(err) { if IsErrSettingIsNotExist(err) {
return SetSetting(ctx, &Setting{ return SetSetting(ctx, &Setting{
SettingKey: key, SettingKey: key,
@ -189,7 +198,7 @@ func SetSettingNoVersion(ctx context.Context, key, value string) error {
// SetSetting updates a users' setting for a specific key // SetSetting updates a users' setting for a specific key
func SetSetting(ctx context.Context, setting *Setting) error { func SetSetting(ctx context.Context, setting *Setting) error {
if err := upsertSettingValue(strings.ToLower(setting.SettingKey), setting.SettingValue, setting.Version); err != nil { if err := upsertSettingValue(ctx, strings.ToLower(setting.SettingKey), setting.SettingValue, setting.Version); err != nil {
return err return err
} }
@ -205,8 +214,8 @@ func SetSetting(ctx context.Context, setting *Setting) error {
return nil return nil
} }
func upsertSettingValue(key, value string, version int) error { func upsertSettingValue(parentCtx context.Context, key, value string, version int) error {
return db.WithTx(db.DefaultContext, func(ctx context.Context) error { return db.WithTx(parentCtx, func(ctx context.Context) error {
e := db.GetEngine(ctx) e := db.GetEngine(ctx)
// here we use a general method to do a safe upsert for different databases (and most transaction levels) // here we use a general method to do a safe upsert for different databases (and most transaction levels)
@ -249,9 +258,9 @@ var (
LibravatarService *libravatar.Libravatar LibravatarService *libravatar.Libravatar
) )
func Init() error { func Init(ctx context.Context) error {
var disableGravatar bool var disableGravatar bool
disableGravatarSetting, err := GetSettingNoCache(db.DefaultContext, KeyPictureDisableGravatar) disableGravatarSetting, err := GetSetting(ctx, KeyPictureDisableGravatar)
if IsErrSettingIsNotExist(err) { if IsErrSettingIsNotExist(err) {
disableGravatar = setting_module.GetDefaultDisableGravatar() disableGravatar = setting_module.GetDefaultDisableGravatar()
disableGravatarSetting = &Setting{SettingValue: strconv.FormatBool(disableGravatar)} disableGravatarSetting = &Setting{SettingValue: strconv.FormatBool(disableGravatar)}
@ -262,7 +271,7 @@ func Init() error {
} }
var enableFederatedAvatar bool var enableFederatedAvatar bool
enableFederatedAvatarSetting, err := GetSettingNoCache(db.DefaultContext, KeyPictureEnableFederatedAvatar) enableFederatedAvatarSetting, err := GetSetting(ctx, KeyPictureEnableFederatedAvatar)
if IsErrSettingIsNotExist(err) { if IsErrSettingIsNotExist(err) {
enableFederatedAvatar = setting_module.GetDefaultEnableFederatedAvatar(disableGravatar) enableFederatedAvatar = setting_module.GetDefaultEnableFederatedAvatar(disableGravatar)
enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(enableFederatedAvatar)} enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(enableFederatedAvatar)}
@ -275,13 +284,13 @@ func Init() error {
if setting_module.OfflineMode { if setting_module.OfflineMode {
disableGravatar = true disableGravatar = true
enableFederatedAvatar = false enableFederatedAvatar = false
if !GetSettingBool(db.DefaultContext, KeyPictureDisableGravatar) { if !GetSettingBool(ctx, KeyPictureDisableGravatar) {
if err := SetSettingNoVersion(db.DefaultContext, KeyPictureDisableGravatar, "true"); err != nil { if err := SetSettingNoVersion(ctx, KeyPictureDisableGravatar, "true"); err != nil {
return fmt.Errorf("Failed to set setting %q: %w", KeyPictureDisableGravatar, err) return fmt.Errorf("Failed to set setting %q: %w", KeyPictureDisableGravatar, err)
} }
} }
if GetSettingBool(db.DefaultContext, KeyPictureEnableFederatedAvatar) { if GetSettingBool(ctx, KeyPictureEnableFederatedAvatar) {
if err := SetSettingNoVersion(db.DefaultContext, KeyPictureEnableFederatedAvatar, "false"); err != nil { if err := SetSettingNoVersion(ctx, KeyPictureEnableFederatedAvatar, "false"); err != nil {
return fmt.Errorf("Failed to set setting %q: %w", KeyPictureEnableFederatedAvatar, err) return fmt.Errorf("Failed to set setting %q: %w", KeyPictureEnableFederatedAvatar, err)
} }
} }

View File

@ -40,10 +40,10 @@ func TestSettings(t *testing.T) {
value, err := system.GetSetting(db.DefaultContext, keyName) value, err := system.GetSetting(db.DefaultContext, keyName)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, updatedSetting.SettingValue, value) assert.EqualValues(t, updatedSetting.SettingValue, value.SettingValue)
// get all settings // get all settings
settings, err = system.GetAllSettings() settings, err = system.GetAllSettings(db.DefaultContext)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, settings, 3) assert.Len(t, settings, 3)
assert.EqualValues(t, updatedSetting.SettingValue, settings[strings.ToLower(updatedSetting.SettingKey)].SettingValue) assert.EqualValues(t, updatedSetting.SettingValue, settings[strings.ToLower(updatedSetting.SettingKey)].SettingValue)
@ -51,7 +51,7 @@ func TestSettings(t *testing.T) {
// delete setting // delete setting
err = system.DeleteSetting(db.DefaultContext, &system.Setting{SettingKey: strings.ToLower(keyName)}) err = system.DeleteSetting(db.DefaultContext, &system.Setting{SettingKey: strings.ToLower(keyName)})
assert.NoError(t, err) assert.NoError(t, err)
settings, err = system.GetAllSettings() settings, err = system.GetAllSettings(db.DefaultContext)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, settings, 2) assert.Len(t, settings, 2)
} }

View File

@ -113,7 +113,7 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
if err = storage.Init(); err != nil { if err = storage.Init(); err != nil {
fatalTestError("storage.Init: %v\n", err) fatalTestError("storage.Init: %v\n", err)
} }
if err = system_model.Init(); err != nil { if err = system_model.Init(db.DefaultContext); err != nil {
fatalTestError("models.Init: %v\n", err) fatalTestError("models.Init: %v\n", err)
} }

View File

@ -67,7 +67,7 @@ func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
useLocalAvatar := false useLocalAvatar := false
autoGenerateAvatar := false autoGenerateAvatar := false
disableGravatar := system_model.GetSettingBool(ctx, system_model.KeyPictureDisableGravatar) disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar)
switch { switch {
case u.UseCustomAvatar: case u.UseCustomAvatar:

View File

@ -106,7 +106,7 @@ func enableGravatar(t *testing.T) {
err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "false") err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "false")
assert.NoError(t, err) assert.NoError(t, err)
setting.GravatarSource = "https://secure.gravatar.com/avatar" setting.GravatarSource = "https://secure.gravatar.com/avatar"
err = system_model.Init() err = system_model.Init(db.DefaultContext)
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -92,7 +92,7 @@ func NewFuncMap() []template.FuncMap {
return setting.AssetVersion return setting.AssetVersion
}, },
"DisableGravatar": func(ctx context.Context) bool { "DisableGravatar": func(ctx context.Context) bool {
return system_model.GetSettingBool(ctx, system_model.KeyPictureDisableGravatar) return system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar)
}, },
"DefaultShowFullName": func() bool { "DefaultShowFullName": func() bool {
return setting.UI.DefaultShowFullName return setting.UI.DefaultShowFullName

View File

@ -150,7 +150,7 @@ func GlobalInitInstalled(ctx context.Context) {
mustInit(system.Init) mustInit(system.Init)
mustInit(oauth2.Init) mustInit(oauth2.Init)
mustInit(models.Init) mustInitCtx(ctx, models.Init)
mustInit(repo_service.Init) mustInit(repo_service.Init)
// Booting long running goroutines. // Booting long running goroutines.

View File

@ -103,7 +103,7 @@ func Config(ctx *context.Context) {
ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminConfig"] = true ctx.Data["PageIsAdminConfig"] = true
systemSettings, err := system_model.GetAllSettings() systemSettings, err := system_model.GetAllSettings(ctx)
if err != nil { if err != nil {
ctx.ServerError("system_model.GetAllSettings", err) ctx.ServerError("system_model.GetAllSettings", err)
return return