Skip to content

Commit bbfb442

Browse files
committed
fix
1 parent 0fe9f93 commit bbfb442

15 files changed

+198
-209
lines changed

.golangci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ linters-settings:
8686
desc: do not use the internal package, use AddXxx function instead
8787
- pkg: gopkg.in/ini.v1
8888
desc: do not use the ini package, use gitea's config system instead
89+
- pkg: gitea.com/go-chi/cache
90+
desc: do not use the go-chi cache package, use gitea's cache system
8991

9092
issues:
9193
max-issues-per-linter: 0

modules/cache/cache.go

+32-106
Original file line numberDiff line numberDiff line change
@@ -4,149 +4,75 @@
44
package cache
55

66
import (
7-
"fmt"
87
"strconv"
8+
"time"
99

1010
"code.gitea.io/gitea/modules/setting"
11-
12-
mc "gitea.com/go-chi/cache"
13-
14-
_ "gitea.com/go-chi/cache/memcache" // memcache plugin for cache
1511
)
1612

17-
var conn mc.Cache
18-
19-
func newCache(cacheConfig setting.Cache) (mc.Cache, error) {
20-
return mc.NewCacher(mc.Options{
21-
Adapter: cacheConfig.Adapter,
22-
AdapterConfig: cacheConfig.Conn,
23-
Interval: cacheConfig.Interval,
24-
})
25-
}
13+
var defaultCache StringCache
2614

2715
// Init start cache service
2816
func Init() error {
29-
var err error
30-
31-
if conn == nil {
32-
if conn, err = newCache(setting.CacheService.Cache); err != nil {
17+
if defaultCache == nil {
18+
c, err := NewStringCache(setting.CacheService.Cache)
19+
if err != nil {
3320
return err
3421
}
35-
if err = conn.Ping(); err != nil {
22+
for i := 0; i < 10; i++ {
23+
if err = c.Ping(); err == nil {
24+
break
25+
}
26+
time.Sleep(time.Second)
27+
}
28+
if err != nil {
3629
return err
3730
}
31+
defaultCache = c
3832
}
39-
40-
return err
33+
return nil
4134
}
4235

4336
// GetCache returns the currently configured cache
44-
func GetCache() mc.Cache {
45-
return conn
37+
func GetCache() StringCache {
38+
return defaultCache
4639
}
4740

4841
// GetString returns the key value from cache with callback when no key exists in cache
4942
func GetString(key string, getFunc func() (string, error)) (string, error) {
50-
if conn == nil || setting.CacheService.TTL == 0 {
43+
if defaultCache == nil || setting.CacheService.TTL == 0 {
5144
return getFunc()
5245
}
53-
54-
cached := conn.Get(key)
55-
56-
if cached == nil {
46+
cached, exist := defaultCache.Get(key)
47+
if !exist {
5748
value, err := getFunc()
5849
if err != nil {
5950
return value, err
6051
}
61-
return value, conn.Put(key, value, setting.CacheService.TTLSeconds())
62-
}
63-
64-
if value, ok := cached.(string); ok {
65-
return value, nil
66-
}
67-
68-
if stringer, ok := cached.(fmt.Stringer); ok {
69-
return stringer.String(), nil
70-
}
71-
72-
return fmt.Sprintf("%s", cached), nil
73-
}
74-
75-
// GetInt returns key value from cache with callback when no key exists in cache
76-
func GetInt(key string, getFunc func() (int, error)) (int, error) {
77-
if conn == nil || setting.CacheService.TTL == 0 {
78-
return getFunc()
79-
}
80-
81-
cached := conn.Get(key)
82-
83-
if cached == nil {
84-
value, err := getFunc()
85-
if err != nil {
86-
return value, err
87-
}
88-
89-
return value, conn.Put(key, value, setting.CacheService.TTLSeconds())
90-
}
91-
92-
switch v := cached.(type) {
93-
case int:
94-
return v, nil
95-
case string:
96-
value, err := strconv.Atoi(v)
97-
if err != nil {
98-
return 0, err
99-
}
100-
return value, nil
101-
default:
102-
value, err := getFunc()
103-
if err != nil {
104-
return value, err
105-
}
106-
return value, conn.Put(key, value, setting.CacheService.TTLSeconds())
52+
return value, defaultCache.Put(key, value, setting.CacheService.TTLSeconds())
10753
}
54+
return cached, nil
10855
}
10956

11057
// GetInt64 returns key value from cache with callback when no key exists in cache
11158
func GetInt64(key string, getFunc func() (int64, error)) (int64, error) {
112-
if conn == nil || setting.CacheService.TTL == 0 {
113-
return getFunc()
114-
}
115-
116-
cached := conn.Get(key)
117-
118-
if cached == nil {
119-
value, err := getFunc()
120-
if err != nil {
121-
return value, err
122-
}
123-
124-
return value, conn.Put(key, value, setting.CacheService.TTLSeconds())
59+
s, err := GetString(key, func() (string, error) {
60+
v, err := getFunc()
61+
return strconv.FormatInt(v, 10), err
62+
})
63+
if err != nil {
64+
return 0, err
12565
}
126-
127-
switch v := conn.Get(key).(type) {
128-
case int64:
129-
return v, nil
130-
case string:
131-
value, err := strconv.ParseInt(v, 10, 64)
132-
if err != nil {
133-
return 0, err
134-
}
135-
return value, nil
136-
default:
137-
value, err := getFunc()
138-
if err != nil {
139-
return value, err
140-
}
141-
142-
return value, conn.Put(key, value, setting.CacheService.TTLSeconds())
66+
if s == "" {
67+
return 0, nil
14368
}
69+
return strconv.ParseInt(s, 10, 64)
14470
}
14571

14672
// Remove key from cache
14773
func Remove(key string) {
148-
if conn == nil {
74+
if defaultCache == nil {
14975
return
15076
}
151-
_ = conn.Delete(key)
77+
_ = defaultCache.Delete(key)
15278
}

modules/cache/cache_redis.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"code.gitea.io/gitea/modules/graceful"
1212
"code.gitea.io/gitea/modules/nosql"
1313

14-
"gitea.com/go-chi/cache"
14+
"gitea.com/go-chi/cache" //nolint:depguard
1515
"github.com/redis/go-redis/v9"
1616
)
1717

modules/cache/cache_test.go

+2-38
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
)
1515

1616
func createTestCache() {
17-
conn, _ = newCache(setting.Cache{
17+
defaultCache, _ = NewStringCache(setting.Cache{
1818
Adapter: "memory",
1919
TTL: time.Minute,
2020
})
@@ -25,7 +25,7 @@ func TestNewContext(t *testing.T) {
2525
assert.NoError(t, Init())
2626

2727
setting.CacheService.Cache = setting.Cache{Adapter: "redis", Conn: "some random string"}
28-
con, err := newCache(setting.Cache{
28+
con, err := NewStringCache(setting.Cache{
2929
Adapter: "rand",
3030
Conn: "false conf",
3131
Interval: 100,
@@ -76,42 +76,6 @@ func TestGetString(t *testing.T) {
7676
Remove("key")
7777
}
7878

79-
func TestGetInt(t *testing.T) {
80-
createTestCache()
81-
82-
data, err := GetInt("key", func() (int, error) {
83-
return 0, fmt.Errorf("some error")
84-
})
85-
assert.Error(t, err)
86-
assert.Equal(t, 0, data)
87-
88-
data, err = GetInt("key", func() (int, error) {
89-
return 0, nil
90-
})
91-
assert.NoError(t, err)
92-
assert.Equal(t, 0, data)
93-
94-
data, err = GetInt("key", func() (int, error) {
95-
return 100, nil
96-
})
97-
assert.NoError(t, err)
98-
assert.Equal(t, 0, data)
99-
Remove("key")
100-
101-
data, err = GetInt("key", func() (int, error) {
102-
return 100, nil
103-
})
104-
assert.NoError(t, err)
105-
assert.Equal(t, 100, data)
106-
107-
data, err = GetInt("key", func() (int, error) {
108-
return 0, fmt.Errorf("some error")
109-
})
110-
assert.NoError(t, err)
111-
assert.Equal(t, 100, data)
112-
Remove("key")
113-
}
114-
11579
func TestGetInt64(t *testing.T) {
11680
createTestCache()
11781

modules/cache/cache_twoqueue.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
"code.gitea.io/gitea/modules/json"
1212

13-
mc "gitea.com/go-chi/cache"
13+
mc "gitea.com/go-chi/cache" //nolint:depguard
1414
lru "github.com/hashicorp/golang-lru/v2"
1515
)
1616

modules/cache/string_cache.go

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

0 commit comments

Comments
 (0)