Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

string_cache.go 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package cache
  4. import (
  5. "errors"
  6. "strings"
  7. "code.gitea.io/gitea/modules/json"
  8. "code.gitea.io/gitea/modules/setting"
  9. "code.gitea.io/gitea/modules/util"
  10. chi_cache "gitea.com/go-chi/cache" //nolint:depguard
  11. )
  12. type GetJSONError struct {
  13. err error
  14. cachedError string // Golang error can't be stored in cache, only the string message could be stored
  15. }
  16. func (e *GetJSONError) ToError() error {
  17. if e.err != nil {
  18. return e.err
  19. }
  20. return errors.New("cached error: " + e.cachedError)
  21. }
  22. type StringCache interface {
  23. Ping() error
  24. Get(key string) (string, bool)
  25. Put(key, value string, ttl int64) error
  26. Delete(key string) error
  27. IsExist(key string) bool
  28. PutJSON(key string, v any, ttl int64) error
  29. GetJSON(key string, ptr any) (exist bool, err *GetJSONError)
  30. ChiCache() chi_cache.Cache
  31. }
  32. type stringCache struct {
  33. chiCache chi_cache.Cache
  34. }
  35. func NewStringCache(cacheConfig setting.Cache) (StringCache, error) {
  36. adapter := util.IfZero(cacheConfig.Adapter, "memory")
  37. interval := util.IfZero(cacheConfig.Interval, 60)
  38. cc, err := chi_cache.NewCacher(chi_cache.Options{
  39. Adapter: adapter,
  40. AdapterConfig: cacheConfig.Conn,
  41. Interval: interval,
  42. })
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &stringCache{chiCache: cc}, nil
  47. }
  48. func (sc *stringCache) Ping() error {
  49. return sc.chiCache.Ping()
  50. }
  51. func (sc *stringCache) Get(key string) (string, bool) {
  52. v := sc.chiCache.Get(key)
  53. if v == nil {
  54. return "", false
  55. }
  56. s, ok := v.(string)
  57. return s, ok
  58. }
  59. func (sc *stringCache) Put(key, value string, ttl int64) error {
  60. return sc.chiCache.Put(key, value, ttl)
  61. }
  62. func (sc *stringCache) Delete(key string) error {
  63. return sc.chiCache.Delete(key)
  64. }
  65. func (sc *stringCache) IsExist(key string) bool {
  66. return sc.chiCache.IsExist(key)
  67. }
  68. const cachedErrorPrefix = "<CACHED-ERROR>:"
  69. func (sc *stringCache) PutJSON(key string, v any, ttl int64) error {
  70. var s string
  71. switch v := v.(type) {
  72. case error:
  73. s = cachedErrorPrefix + v.Error()
  74. default:
  75. b, err := json.Marshal(v)
  76. if err != nil {
  77. return err
  78. }
  79. s = util.UnsafeBytesToString(b)
  80. }
  81. return sc.chiCache.Put(key, s, ttl)
  82. }
  83. func (sc *stringCache) GetJSON(key string, ptr any) (exist bool, getErr *GetJSONError) {
  84. s, ok := sc.Get(key)
  85. if !ok || s == "" {
  86. return false, nil
  87. }
  88. s, isCachedError := strings.CutPrefix(s, cachedErrorPrefix)
  89. if isCachedError {
  90. return true, &GetJSONError{cachedError: s}
  91. }
  92. if err := json.Unmarshal(util.UnsafeStringToBytes(s), ptr); err != nil {
  93. return false, &GetJSONError{err: err}
  94. }
  95. return true, nil
  96. }
  97. func (sc *stringCache) ChiCache() chi_cache.Cache {
  98. return sc.chiCache
  99. }