gitea源码

setting.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package system
  4. import (
  5. "context"
  6. "math"
  7. "sync"
  8. "time"
  9. "code.gitea.io/gitea/models/db"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/setting/config"
  12. "code.gitea.io/gitea/modules/timeutil"
  13. "xorm.io/builder"
  14. )
  15. type Setting struct {
  16. ID int64 `xorm:"pk autoincr"`
  17. SettingKey string `xorm:"varchar(255) unique"` // key should be lowercase
  18. SettingValue string `xorm:"text"`
  19. Version int `xorm:"version"`
  20. Created timeutil.TimeStamp `xorm:"created"`
  21. Updated timeutil.TimeStamp `xorm:"updated"`
  22. }
  23. // TableName sets the table name for the settings struct
  24. func (s *Setting) TableName() string {
  25. return "system_setting"
  26. }
  27. func init() {
  28. db.RegisterModel(new(Setting))
  29. }
  30. const keyRevision = "revision"
  31. func GetRevision(ctx context.Context) int {
  32. revision, exist, err := db.Get[Setting](ctx, builder.Eq{"setting_key": keyRevision})
  33. if err != nil {
  34. return 0
  35. } else if !exist {
  36. err = db.Insert(ctx, &Setting{SettingKey: keyRevision, Version: 1})
  37. if err != nil {
  38. return 0
  39. }
  40. return 1
  41. }
  42. if revision.Version <= 0 || revision.Version >= math.MaxInt-1 {
  43. _, err = db.Exec(ctx, "UPDATE system_setting SET version=1 WHERE setting_key=?", keyRevision)
  44. if err != nil {
  45. return 0
  46. }
  47. return 1
  48. }
  49. return revision.Version
  50. }
  51. func GetAllSettings(ctx context.Context) (revision int, res map[string]string, err error) {
  52. _ = GetRevision(ctx) // prepare the "revision" key ahead
  53. var settings []*Setting
  54. if err := db.GetEngine(ctx).
  55. Find(&settings); err != nil {
  56. return 0, nil, err
  57. }
  58. res = make(map[string]string)
  59. for _, s := range settings {
  60. if s.SettingKey == keyRevision {
  61. revision = s.Version
  62. }
  63. res[s.SettingKey] = s.SettingValue
  64. }
  65. return revision, res, nil
  66. }
  67. func SetSettings(ctx context.Context, settings map[string]string) error {
  68. _ = GetRevision(ctx) // prepare the "revision" key ahead
  69. return db.WithTx(ctx, func(ctx context.Context) error {
  70. e := db.GetEngine(ctx)
  71. _, err := db.Exec(ctx, "UPDATE system_setting SET version=version+1 WHERE setting_key=?", keyRevision)
  72. if err != nil {
  73. return err
  74. }
  75. for k, v := range settings {
  76. res, err := e.Exec("UPDATE system_setting SET version=version+1, setting_value=? WHERE setting_key=?", v, k)
  77. if err != nil {
  78. return err
  79. }
  80. rows, _ := res.RowsAffected()
  81. if rows == 0 { // if no existing row, insert a new row
  82. if _, err = e.Insert(&Setting{SettingKey: k, SettingValue: v}); err != nil {
  83. return err
  84. }
  85. }
  86. }
  87. return nil
  88. })
  89. }
  90. type dbConfigCachedGetter struct {
  91. mu sync.RWMutex
  92. cacheTime time.Time
  93. revision int
  94. settings map[string]string
  95. }
  96. var _ config.DynKeyGetter = (*dbConfigCachedGetter)(nil)
  97. func (d *dbConfigCachedGetter) GetValue(ctx context.Context, key string) (v string, has bool) {
  98. d.mu.RLock()
  99. defer d.mu.RUnlock()
  100. v, has = d.settings[key]
  101. return v, has
  102. }
  103. func (d *dbConfigCachedGetter) GetRevision(ctx context.Context) int {
  104. d.mu.RLock()
  105. cachedDuration := time.Since(d.cacheTime)
  106. cachedRevision := d.revision
  107. d.mu.RUnlock()
  108. if cachedDuration < time.Second {
  109. return cachedRevision
  110. }
  111. d.mu.Lock()
  112. defer d.mu.Unlock()
  113. if GetRevision(ctx) != d.revision {
  114. rev, set, err := GetAllSettings(ctx)
  115. if err != nil {
  116. log.Error("Unable to get all settings: %v", err)
  117. } else {
  118. d.revision = rev
  119. d.settings = set
  120. }
  121. }
  122. d.cacheTime = time.Now()
  123. return d.revision
  124. }
  125. func (d *dbConfigCachedGetter) InvalidateCache() {
  126. d.mu.Lock()
  127. d.cacheTime = time.Time{}
  128. d.mu.Unlock()
  129. }
  130. func NewDatabaseDynKeyGetter() config.DynKeyGetter {
  131. return &dbConfigCachedGetter{}
  132. }