You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cache.go 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package cache
  5. import (
  6. "fmt"
  7. "strconv"
  8. "code.gitea.io/gitea/modules/log"
  9. "code.gitea.io/gitea/modules/setting"
  10. mc "gitea.com/go-chi/cache"
  11. _ "gitea.com/go-chi/cache/memcache" // memcache plugin for cache
  12. )
  13. var (
  14. conn mc.Cache
  15. )
  16. func newCache(cacheConfig setting.Cache) (mc.Cache, error) {
  17. return mc.NewCacher(mc.Options{
  18. Adapter: cacheConfig.Adapter,
  19. AdapterConfig: cacheConfig.Conn,
  20. Interval: cacheConfig.Interval,
  21. })
  22. }
  23. // NewContext start cache service
  24. func NewContext() error {
  25. var err error
  26. if conn == nil && setting.CacheService.Enabled {
  27. if conn, err = newCache(setting.CacheService.Cache); err != nil {
  28. return err
  29. }
  30. const testKey = "__gitea_cache_test"
  31. const testVal = "test-value"
  32. if err = conn.Put(testKey, testVal, 10); err != nil {
  33. return err
  34. }
  35. val := conn.Get(testKey)
  36. if valStr, ok := val.(string); !ok || valStr != testVal {
  37. // If the cache is full, the Get may not read the expected value stored by Put.
  38. // Since we have checked that Put can success, so we just show a warning here, do not return an error to panic.
  39. log.Warn("cache (adapter:%s, config:%s) doesn't seem to work correctly, set test value '%v' but get '%v'",
  40. setting.CacheService.Cache.Adapter, setting.CacheService.Cache.Conn,
  41. testVal, val,
  42. )
  43. }
  44. }
  45. return err
  46. }
  47. // GetCache returns the currently configured cache
  48. func GetCache() mc.Cache {
  49. return conn
  50. }
  51. // GetString returns the key value from cache with callback when no key exists in cache
  52. func GetString(key string, getFunc func() (string, error)) (string, error) {
  53. if conn == nil || setting.CacheService.TTL == 0 {
  54. return getFunc()
  55. }
  56. if !conn.IsExist(key) {
  57. var (
  58. value string
  59. err error
  60. )
  61. if value, err = getFunc(); err != nil {
  62. return value, err
  63. }
  64. err = conn.Put(key, value, setting.CacheService.TTLSeconds())
  65. if err != nil {
  66. return "", err
  67. }
  68. }
  69. value := conn.Get(key)
  70. if v, ok := value.(string); ok {
  71. return v, nil
  72. }
  73. if v, ok := value.(fmt.Stringer); ok {
  74. return v.String(), nil
  75. }
  76. return fmt.Sprintf("%s", conn.Get(key)), nil
  77. }
  78. // GetInt returns key value from cache with callback when no key exists in cache
  79. func GetInt(key string, getFunc func() (int, error)) (int, error) {
  80. if conn == nil || setting.CacheService.TTL == 0 {
  81. return getFunc()
  82. }
  83. if !conn.IsExist(key) {
  84. var (
  85. value int
  86. err error
  87. )
  88. if value, err = getFunc(); err != nil {
  89. return value, err
  90. }
  91. err = conn.Put(key, value, setting.CacheService.TTLSeconds())
  92. if err != nil {
  93. return 0, err
  94. }
  95. }
  96. switch value := conn.Get(key).(type) {
  97. case int:
  98. return value, nil
  99. case string:
  100. v, err := strconv.Atoi(value)
  101. if err != nil {
  102. return 0, err
  103. }
  104. return v, nil
  105. default:
  106. return 0, fmt.Errorf("Unsupported cached value type: %v", value)
  107. }
  108. }
  109. // GetInt64 returns key value from cache with callback when no key exists in cache
  110. func GetInt64(key string, getFunc func() (int64, error)) (int64, error) {
  111. if conn == nil || setting.CacheService.TTL == 0 {
  112. return getFunc()
  113. }
  114. if !conn.IsExist(key) {
  115. var (
  116. value int64
  117. err error
  118. )
  119. if value, err = getFunc(); err != nil {
  120. return value, err
  121. }
  122. err = conn.Put(key, value, setting.CacheService.TTLSeconds())
  123. if err != nil {
  124. return 0, err
  125. }
  126. }
  127. switch value := conn.Get(key).(type) {
  128. case int64:
  129. return value, nil
  130. case string:
  131. v, err := strconv.ParseInt(value, 10, 64)
  132. if err != nil {
  133. return 0, err
  134. }
  135. return v, nil
  136. default:
  137. return 0, fmt.Errorf("Unsupported cached value type: %v", value)
  138. }
  139. }
  140. // Remove key from cache
  141. func Remove(key string) {
  142. if conn == nil {
  143. return
  144. }
  145. _ = conn.Delete(key)
  146. }