gitea源码

cache.go 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package cache
  4. import (
  5. "encoding/hex"
  6. "errors"
  7. "fmt"
  8. "strconv"
  9. "time"
  10. "code.gitea.io/gitea/modules/setting"
  11. _ "gitea.com/go-chi/cache/memcache" //nolint:depguard // memcache plugin for cache, it is required for config "ADAPTER=memcache"
  12. )
  13. var defaultCache StringCache
  14. // Init start cache service
  15. func Init() error {
  16. if defaultCache == nil {
  17. c, err := NewStringCache(setting.CacheService.Cache)
  18. if err != nil {
  19. return err
  20. }
  21. for range 10 {
  22. if err = c.Ping(); err == nil {
  23. break
  24. }
  25. time.Sleep(time.Second)
  26. }
  27. if err != nil {
  28. return err
  29. }
  30. defaultCache = c
  31. }
  32. return nil
  33. }
  34. const (
  35. testCacheKey = "DefaultCache.TestKey"
  36. // SlowCacheThreshold marks cache tests as slow
  37. // set to 30ms per discussion: https://github.com/go-gitea/gitea/issues/33190
  38. // TODO: Replace with metrics histogram
  39. SlowCacheThreshold = 30 * time.Millisecond
  40. )
  41. // Test performs delete, put and get operations on a predefined key
  42. // returns
  43. func Test() (time.Duration, error) {
  44. if defaultCache == nil {
  45. return 0, errors.New("default cache not initialized")
  46. }
  47. testData := hex.EncodeToString(make([]byte, 500))
  48. start := time.Now()
  49. if err := defaultCache.Delete(testCacheKey); err != nil {
  50. return 0, fmt.Errorf("expect cache to delete data based on key if exist but got: %w", err)
  51. }
  52. if err := defaultCache.Put(testCacheKey, testData, 10); err != nil {
  53. return 0, fmt.Errorf("expect cache to store data but got: %w", err)
  54. }
  55. testVal, hit := defaultCache.Get(testCacheKey)
  56. if !hit {
  57. return 0, errors.New("expect cache hit but got none")
  58. }
  59. if testVal != testData {
  60. return 0, errors.New("expect cache to return same value as stored but got other")
  61. }
  62. return time.Since(start), nil
  63. }
  64. // GetCache returns the currently configured cache
  65. func GetCache() StringCache {
  66. return defaultCache
  67. }
  68. // GetString returns the key value from cache with callback when no key exists in cache
  69. func GetString(key string, getFunc func() (string, error)) (string, error) {
  70. if defaultCache == nil || setting.CacheService.TTL == 0 {
  71. return getFunc()
  72. }
  73. cached, exist := defaultCache.Get(key)
  74. if !exist {
  75. value, err := getFunc()
  76. if err != nil {
  77. return value, err
  78. }
  79. return value, defaultCache.Put(key, value, setting.CacheService.TTLSeconds())
  80. }
  81. return cached, nil
  82. }
  83. // GetInt64 returns key value from cache with callback when no key exists in cache
  84. func GetInt64(key string, getFunc func() (int64, error)) (int64, error) {
  85. s, err := GetString(key, func() (string, error) {
  86. v, err := getFunc()
  87. return strconv.FormatInt(v, 10), err
  88. })
  89. if err != nil {
  90. return 0, err
  91. }
  92. if s == "" {
  93. return 0, nil
  94. }
  95. return strconv.ParseInt(s, 10, 64)
  96. }
  97. // Remove key from cache
  98. func Remove(key string) {
  99. if defaultCache == nil {
  100. return
  101. }
  102. _ = defaultCache.Delete(key)
  103. }