gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package config
  4. import (
  5. "context"
  6. "sync"
  7. "code.gitea.io/gitea/modules/json"
  8. "code.gitea.io/gitea/modules/log"
  9. "code.gitea.io/gitea/modules/util"
  10. )
  11. type CfgSecKey struct {
  12. Sec, Key string
  13. }
  14. type Value[T any] struct {
  15. mu sync.RWMutex
  16. cfgSecKey CfgSecKey
  17. dynKey string
  18. def, value T
  19. revision int
  20. }
  21. func (value *Value[T]) parse(key, valStr string) (v T) {
  22. v = value.def
  23. if valStr != "" {
  24. if err := json.Unmarshal(util.UnsafeStringToBytes(valStr), &v); err != nil {
  25. log.Error("Unable to unmarshal json config for key %q, err: %v", key, err)
  26. }
  27. }
  28. return v
  29. }
  30. func (value *Value[T]) Value(ctx context.Context) (v T) {
  31. dg := GetDynGetter()
  32. if dg == nil {
  33. // this is an edge case: the database is not initialized but the system setting is going to be used
  34. // it should panic to avoid inconsistent config values (from config / system setting) and fix the code
  35. panic("no config dyn value getter")
  36. }
  37. rev := dg.GetRevision(ctx)
  38. // if the revision in the database doesn't change, use the last value
  39. value.mu.RLock()
  40. if rev == value.revision {
  41. v = value.value
  42. value.mu.RUnlock()
  43. return v
  44. }
  45. value.mu.RUnlock()
  46. // try to parse the config and cache it
  47. var valStr *string
  48. if dynVal, has := dg.GetValue(ctx, value.dynKey); has {
  49. valStr = &dynVal
  50. } else if cfgVal, has := GetCfgSecKeyGetter().GetValue(value.cfgSecKey.Sec, value.cfgSecKey.Key); has {
  51. valStr = &cfgVal
  52. }
  53. if valStr == nil {
  54. v = value.def
  55. } else {
  56. v = value.parse(value.dynKey, *valStr)
  57. }
  58. value.mu.Lock()
  59. value.value = v
  60. value.revision = rev
  61. value.mu.Unlock()
  62. return v
  63. }
  64. func (value *Value[T]) DynKey() string {
  65. return value.dynKey
  66. }
  67. func (value *Value[T]) WithDefault(def T) *Value[T] {
  68. value.def = def
  69. return value
  70. }
  71. func (value *Value[T]) DefaultValue() T {
  72. return value.def
  73. }
  74. func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] {
  75. value.cfgSecKey = cfgSecKey
  76. return value
  77. }
  78. func ValueJSON[T any](dynKey string) *Value[T] {
  79. return &Value[T]{dynKey: dynKey}
  80. }