mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-24 06:15:42 +03:00
[FEAT] Only implement used API of Redis client
- Currently for the `nosql` module (which simply said provides a manager for redis clients) returns the [`redis.UniversalClient`](https://pkg.go.dev/github.com/redis/go-redis/v9#UniversalClient) interface. The interfaces exposes all available commands. - In generalm, dead code elimination should be able to take care of not generating the machine code for methods that aren't being used. However in this specific case, dead code elimination either is disabled or gives up on trying because of exhaustive call stack the client by `GetRedisClient` is used. - Help the Go compiler by explicitly specifying which methods we use. This reduces the binary size by ~400KB (397312 bytes). As Go no longer generate machine code for commands that aren't being used. - There's a **CAVEAT** with this, if a developer wants to use a new method that isn't specified, they will have to know about this hack (by following the definition of existing Redis methods) and add the method definition from the Redis library to the `RedisClient` interface.
This commit is contained in:
parent
1004ecd56b
commit
9df10c5ac5
5 changed files with 52 additions and 16 deletions
3
modules/cache/cache_redis.go
vendored
3
modules/cache/cache_redis.go
vendored
|
@ -12,12 +12,11 @@ import (
|
|||
"code.gitea.io/gitea/modules/nosql"
|
||||
|
||||
"code.forgejo.org/go-chi/cache"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// RedisCacher represents a redis cache adapter implementation.
|
||||
type RedisCacher struct {
|
||||
c redis.UniversalClient
|
||||
c nosql.RedisClient
|
||||
prefix string
|
||||
hsetName string
|
||||
occupyMode bool
|
||||
|
|
|
@ -27,8 +27,46 @@ type Manager struct {
|
|||
LevelDBConnections map[string]*levelDBHolder
|
||||
}
|
||||
|
||||
// RedisClient is a subset of redis.UniversalClient, it exposes less methods
|
||||
// to avoid generating machine code for unused methods. New method definitions
|
||||
// should be copied from the definitions in the Redis library github.com/redis/go-redis.
|
||||
type RedisClient interface {
|
||||
// redis.GenericCmdable
|
||||
Del(ctx context.Context, keys ...string) *redis.IntCmd
|
||||
Exists(ctx context.Context, keys ...string) *redis.IntCmd
|
||||
|
||||
// redis.ListCmdable
|
||||
RPush(ctx context.Context, key string, values ...any) *redis.IntCmd
|
||||
LPop(ctx context.Context, key string) *redis.StringCmd
|
||||
LLen(ctx context.Context, key string) *redis.IntCmd
|
||||
|
||||
// redis.StringCmdable
|
||||
Decr(ctx context.Context, key string) *redis.IntCmd
|
||||
Incr(ctx context.Context, key string) *redis.IntCmd
|
||||
Set(ctx context.Context, key string, value any, expiration time.Duration) *redis.StatusCmd
|
||||
Get(ctx context.Context, key string) *redis.StringCmd
|
||||
|
||||
// redis.HashCmdable
|
||||
HSet(ctx context.Context, key string, values ...any) *redis.IntCmd
|
||||
HDel(ctx context.Context, key string, fields ...string) *redis.IntCmd
|
||||
HKeys(ctx context.Context, key string) *redis.StringSliceCmd
|
||||
|
||||
// redis.SetCmdable
|
||||
SAdd(ctx context.Context, key string, members ...any) *redis.IntCmd
|
||||
SRem(ctx context.Context, key string, members ...any) *redis.IntCmd
|
||||
SIsMember(ctx context.Context, key string, member any) *redis.BoolCmd
|
||||
|
||||
// redis.Cmdable
|
||||
DBSize(ctx context.Context) *redis.IntCmd
|
||||
FlushDB(ctx context.Context) *redis.StatusCmd
|
||||
Ping(ctx context.Context) *redis.StatusCmd
|
||||
|
||||
// redis.UniversalClient
|
||||
Close() error
|
||||
}
|
||||
|
||||
type redisClientHolder struct {
|
||||
redis.UniversalClient
|
||||
RedisClient
|
||||
name []string
|
||||
count int64
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@ func (m *Manager) CloseRedisClient(connection string) error {
|
|||
for _, name := range client.name {
|
||||
delete(m.RedisConnections, name)
|
||||
}
|
||||
return client.UniversalClient.Close()
|
||||
return client.RedisClient.Close()
|
||||
}
|
||||
|
||||
// GetRedisClient gets a redis client for a particular connection
|
||||
func (m *Manager) GetRedisClient(connection string) (client redis.UniversalClient) {
|
||||
func (m *Manager) GetRedisClient(connection string) (client RedisClient) {
|
||||
// Because we want associate any goroutines created by this call to the main nosqldb context we need to
|
||||
// wrap this in a goroutine labelled with the nosqldb context
|
||||
done := make(chan struct{})
|
||||
|
@ -67,7 +67,7 @@ func (m *Manager) GetRedisClient(connection string) (client redis.UniversalClien
|
|||
return client
|
||||
}
|
||||
|
||||
func (m *Manager) getRedisClient(connection string) redis.UniversalClient {
|
||||
func (m *Manager) getRedisClient(connection string) RedisClient {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
client, ok := m.RedisConnections[connection]
|
||||
|
@ -102,24 +102,24 @@ func (m *Manager) getRedisClient(connection string) redis.UniversalClient {
|
|||
opts.TLSConfig = tlsConfig
|
||||
fallthrough
|
||||
case "redis+sentinel":
|
||||
client.UniversalClient = redis.NewFailoverClient(opts.Failover())
|
||||
client.RedisClient = redis.NewFailoverClient(opts.Failover())
|
||||
case "redis+clusters":
|
||||
fallthrough
|
||||
case "rediss+cluster":
|
||||
opts.TLSConfig = tlsConfig
|
||||
fallthrough
|
||||
case "redis+cluster":
|
||||
client.UniversalClient = redis.NewClusterClient(opts.Cluster())
|
||||
client.RedisClient = redis.NewClusterClient(opts.Cluster())
|
||||
case "redis+socket":
|
||||
simpleOpts := opts.Simple()
|
||||
simpleOpts.Network = "unix"
|
||||
simpleOpts.Addr = path.Join(uri.Host, uri.Path)
|
||||
client.UniversalClient = redis.NewClient(simpleOpts)
|
||||
client.RedisClient = redis.NewClient(simpleOpts)
|
||||
case "rediss":
|
||||
opts.TLSConfig = tlsConfig
|
||||
fallthrough
|
||||
case "redis":
|
||||
client.UniversalClient = redis.NewClient(opts.Simple())
|
||||
client.RedisClient = redis.NewClient(opts.Simple())
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
type baseRedis struct {
|
||||
client redis.UniversalClient
|
||||
client nosql.RedisClient
|
||||
isUnique bool
|
||||
cfg *BaseConfig
|
||||
prefix string
|
||||
|
@ -26,7 +26,7 @@ type baseRedis struct {
|
|||
|
||||
var _ baseQueue = (*baseRedis)(nil)
|
||||
|
||||
func newBaseRedisGeneric(cfg *BaseConfig, unique bool, client redis.UniversalClient) (baseQueue, error) {
|
||||
func newBaseRedisGeneric(cfg *BaseConfig, unique bool, client nosql.RedisClient) (baseQueue, error) {
|
||||
if client == nil {
|
||||
client = nosql.GetManager().GetRedisClient(cfg.ConnStr)
|
||||
}
|
||||
|
|
|
@ -26,12 +26,11 @@ import (
|
|||
"code.gitea.io/gitea/modules/nosql"
|
||||
|
||||
"code.forgejo.org/go-chi/session"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// RedisStore represents a redis session store implementation.
|
||||
type RedisStore struct {
|
||||
c redis.UniversalClient
|
||||
c nosql.RedisClient
|
||||
prefix, sid string
|
||||
duration time.Duration
|
||||
lock sync.RWMutex
|
||||
|
@ -39,7 +38,7 @@ type RedisStore struct {
|
|||
}
|
||||
|
||||
// NewRedisStore creates and returns a redis session store.
|
||||
func NewRedisStore(c redis.UniversalClient, prefix, sid string, dur time.Duration, kv map[any]any) *RedisStore {
|
||||
func NewRedisStore(c nosql.RedisClient, prefix, sid string, dur time.Duration, kv map[any]any) *RedisStore {
|
||||
return &RedisStore{
|
||||
c: c,
|
||||
prefix: prefix,
|
||||
|
@ -106,7 +105,7 @@ func (s *RedisStore) Flush() error {
|
|||
|
||||
// RedisProvider represents a redis session provider implementation.
|
||||
type RedisProvider struct {
|
||||
c redis.UniversalClient
|
||||
c nosql.RedisClient
|
||||
duration time.Duration
|
||||
prefix string
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue