-
Notifications
You must be signed in to change notification settings - Fork 5
/
caching_store.go
112 lines (88 loc) · 2.36 KB
/
caching_store.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package gbox
import (
"errors"
"fmt"
"net/url"
"strconv"
"sync"
"github.com/coocood/freecache"
"github.com/eko/gocache/v2/marshaler"
"github.com/eko/gocache/v2/store"
"github.com/go-redis/redis/v8"
)
var (
cachingStoreFactories = make(map[string]CachingStoreFactory)
cachingStoreFactoriesMu sync.RWMutex
)
func init() { // nolint:gochecknoinits
RegisterCachingStoreFactory("redis", RedisCachingStoreFactory)
RegisterCachingStoreFactory("freecache", FreeCacheStoreFactory)
}
type CachingStore struct {
*marshaler.Marshaler
close func() error
}
type CachingStoreFactory = func(u *url.URL) (*CachingStore, error)
func RegisterCachingStoreFactory(schema string, factory CachingStoreFactory) {
cachingStoreFactoriesMu.Lock()
defer cachingStoreFactoriesMu.Unlock()
cachingStoreFactories[schema] = factory
}
func NewCachingStore(u *url.URL) (*CachingStore, error) {
cachingStoreFactoriesMu.RLock()
defer cachingStoreFactoriesMu.RUnlock()
factory, ok := cachingStoreFactories[u.Scheme]
if !ok {
return nil, fmt.Errorf("caching store schema: %s is not support", u.Scheme)
}
return factory(u)
}
func FreeCacheStoreFactory(u *url.URL) (*CachingStore, error) {
q := u.Query()
cacheSize := q.Get("cache_size")
if cacheSize == "" {
return nil, errors.New("cache_size must be set explicit")
}
cacheSizeInt, err := strconv.Atoi(cacheSize)
if err != nil {
return nil, fmt.Errorf("`cache_size` param should be numeric string, %s given", cacheSize)
}
client := freecache.NewCache(cacheSizeInt)
freeCacheStore := store.NewFreecache(client, nil)
return &CachingStore{
Marshaler: marshaler.New(freeCacheStore),
close: func() error {
client.Clear()
return nil
},
}, nil
}
func RedisCachingStoreFactory(u *url.URL) (*CachingStore, error) {
q := u.Query()
opts := &redis.Options{
Addr: u.Host,
}
if v := q.Get("db"); v != "" {
db, err := strconv.Atoi(v)
if err != nil {
return nil, fmt.Errorf("`db` param should be numeric string, %s given", v)
}
opts.DB = db
}
user := u.User.Username()
password, hasPassword := u.User.Password()
if !hasPassword {
opts.Password = user
} else {
opts.Username = user
opts.Password = password
}
client := redis.NewClient(opts)
redisStore := store.NewRedis(client, nil)
return &CachingStore{
Marshaler: marshaler.New(redisStore),
close: func() error {
return client.Close()
},
}, nil
}