-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcache.go
More file actions
74 lines (66 loc) · 2.53 KB
/
cache.go
File metadata and controls
74 lines (66 loc) · 2.53 KB
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
package quotacontrol
import (
"fmt"
"log/slog"
"time"
"github.com/0xsequence/go-libs/xlog"
"github.com/go-chi/httprate"
httprateredis "github.com/go-chi/httprate-redis"
"github.com/redis/go-redis/v9"
"github.com/0xsequence/quotacontrol/cache"
"github.com/0xsequence/quotacontrol/proto"
)
type Cache struct {
AccessKeys cache.Simple[KeyAccessKey, *proto.AccessQuota]
Projects cache.Simple[KeyProject, *proto.AccessQuota]
Permissions cache.Simple[KeyPermission, UserPermission]
Usage cache.Usage[KeyUsage]
ProjectInfo cache.Simple[KeyProjectInfo, *proto.ProjectInfo]
Limits cache.Simple[KeyLimit, *proto.Limit]
Keys cache.Simple[KeyAccessKeyV2, *proto.AccessKey]
}
// NewCache creates a Cache backed by Redis using the new generic cache package.
func NewCache(client *redis.Client, ttl time.Duration, lruSize int, lruExpiration time.Duration) Cache {
backend := cache.NewBackend(client, ttl)
c := Cache{
AccessKeys: cache.RedisCache[KeyAccessKey, *proto.AccessQuota]{Backend: backend},
Projects: cache.RedisCache[KeyProject, *proto.AccessQuota]{Backend: backend},
Permissions: cache.RedisCache[KeyPermission, UserPermission]{Backend: backend},
Usage: cache.NewUsageCache[KeyUsage](backend),
ProjectInfo: cache.RedisCache[KeyProjectInfo, *proto.ProjectInfo]{Backend: backend},
Limits: cache.RedisCache[KeyLimit, *proto.Limit]{Backend: backend},
Keys: cache.RedisCache[KeyAccessKeyV2, *proto.AccessKey]{Backend: backend},
}
if lruSize > 0 {
c.AccessKeys = cache.NewMemory(c.AccessKeys, lruSize, lruExpiration)
c.Projects = cache.NewMemory(c.Projects, lruSize, lruExpiration)
c.Permissions = cache.NewMemory(c.Permissions, lruSize, lruExpiration)
c.ProjectInfo = cache.NewMemory(c.ProjectInfo, lruSize, lruExpiration)
c.Limits = cache.NewMemory(c.Limits, lruSize, lruExpiration)
c.Keys = cache.NewMemory(c.Keys, lruSize, lruExpiration)
}
return c
}
const (
redisRLPrefix = "rl:"
)
func NewLimitCounter(svc proto.Service, cfg RedisConfig, logger *slog.Logger) httprate.LimitCounter {
return httprateredis.NewCounter(&httprateredis.Config{
Host: cfg.Host,
Port: cfg.Port,
MaxIdle: cfg.MaxIdle,
MaxActive: cfg.MaxActive,
DBIndex: cfg.DBIndex,
PrefixKey: fmt.Sprintf("%s%s:", redisRLPrefix, svc),
OnError: func(err error) {
if logger != nil {
logger.Error("redis counter error", xlog.Error(err))
}
},
OnFallbackChange: func(fallback bool) {
if logger != nil {
logger.Warn("redis counter fallback", slog.Bool("fallback", fallback))
}
},
})
}