251 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
|  * Copyright 2025 coze-dev Authors
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| package redis
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"os"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/redis/go-redis/v9"
 | |
| 
 | |
| 	"github.com/coze-dev/coze-studio/backend/infra/contract/cache"
 | |
| )
 | |
| 
 | |
| func New() cache.Cmdable {
 | |
| 	addr := os.Getenv("REDIS_ADDR")
 | |
| 	password := os.Getenv("REDIS_PASSWORD")
 | |
| 
 | |
| 	return NewWithAddrAndPassword(addr, password)
 | |
| }
 | |
| 
 | |
| func NewWithAddrAndPassword(addr, password string) cache.Cmdable {
 | |
| 	cache.SetDefaultNilError(redis.Nil)
 | |
| 
 | |
| 	rdb := redis.NewClient(&redis.Options{
 | |
| 		Addr:     addr, // Redis地址
 | |
| 		DB:       0,    // 默认数据库
 | |
| 		Password: password,
 | |
| 		// connection pool configuration
 | |
| 		PoolSize:        100,             // Maximum number of connections (recommended to set to CPU cores * 10)
 | |
| 		MinIdleConns:    10,              // minimum idle connection
 | |
| 		MaxIdleConns:    30,              // maximum idle connection
 | |
| 		ConnMaxIdleTime: 5 * time.Minute, // Idle connection timeout
 | |
| 
 | |
| 		// timeout configuration
 | |
| 		DialTimeout:  5 * time.Second, // Connection establishment timed out
 | |
| 		ReadTimeout:  3 * time.Second, // read operation timed out
 | |
| 		WriteTimeout: 3 * time.Second, // write operation timed out
 | |
| 	})
 | |
| 
 | |
| 	return &redisImpl{client: rdb}
 | |
| }
 | |
| 
 | |
| type redisImpl struct {
 | |
| 	client *redis.Client
 | |
| }
 | |
| 
 | |
| // Del implements cache.Cmdable.
 | |
| func (r *redisImpl) Del(ctx context.Context, keys ...string) cache.IntCmd {
 | |
| 	return r.client.Del(ctx, keys...)
 | |
| }
 | |
| 
 | |
| // Exists implements cache.Cmdable.
 | |
| func (r *redisImpl) Exists(ctx context.Context, keys ...string) cache.IntCmd {
 | |
| 	return r.client.Exists(ctx, keys...)
 | |
| }
 | |
| 
 | |
| // Expire implements cache.Cmdable.
 | |
| func (r *redisImpl) Expire(ctx context.Context, key string, expiration time.Duration) cache.BoolCmd {
 | |
| 	return r.client.Expire(ctx, key, expiration)
 | |
| }
 | |
| 
 | |
| // Get implements cache.Cmdable.
 | |
| func (r *redisImpl) Get(ctx context.Context, key string) cache.StringCmd {
 | |
| 	return r.client.Get(ctx, key)
 | |
| }
 | |
| 
 | |
| // HGetAll implements cache.Cmdable.
 | |
| func (r *redisImpl) HGetAll(ctx context.Context, key string) cache.MapStringStringCmd {
 | |
| 	return r.client.HGetAll(ctx, key)
 | |
| }
 | |
| 
 | |
| // HSet implements cache.Cmdable.
 | |
| func (r *redisImpl) HSet(ctx context.Context, key string, values ...interface{}) cache.IntCmd {
 | |
| 	return r.client.HSet(ctx, key, values...)
 | |
| }
 | |
| 
 | |
| // Incr implements cache.Cmdable.
 | |
| func (r *redisImpl) Incr(ctx context.Context, key string) cache.IntCmd {
 | |
| 	return r.client.Incr(ctx, key)
 | |
| }
 | |
| 
 | |
| // IncrBy implements cache.Cmdable.
 | |
| func (r *redisImpl) IncrBy(ctx context.Context, key string, value int64) cache.IntCmd {
 | |
| 	return r.client.IncrBy(ctx, key, value)
 | |
| }
 | |
| 
 | |
| // LIndex implements cache.Cmdable.
 | |
| func (r *redisImpl) LIndex(ctx context.Context, key string, index int64) cache.StringCmd {
 | |
| 	return r.client.LIndex(ctx, key, index)
 | |
| }
 | |
| 
 | |
| // LPop implements cache.Cmdable.
 | |
| func (r *redisImpl) LPop(ctx context.Context, key string) cache.StringCmd {
 | |
| 	return r.client.LPop(ctx, key)
 | |
| }
 | |
| 
 | |
| // LPush implements cache.Cmdable.
 | |
| func (r *redisImpl) LPush(ctx context.Context, key string, values ...interface{}) cache.IntCmd {
 | |
| 	return r.client.LPush(ctx, key, values...)
 | |
| }
 | |
| 
 | |
| // LRange implements cache.Cmdable.
 | |
| func (r *redisImpl) LRange(ctx context.Context, key string, start int64, stop int64) cache.StringSliceCmd {
 | |
| 	return r.client.LRange(ctx, key, start, stop)
 | |
| }
 | |
| 
 | |
| // LSet implements cache.Cmdable.
 | |
| func (r *redisImpl) LSet(ctx context.Context, key string, index int64, value interface{}) cache.StatusCmd {
 | |
| 	return r.client.LSet(ctx, key, index, value)
 | |
| }
 | |
| 
 | |
| // Pipeline implements cache.Cmdable.
 | |
| func (r *redisImpl) Pipeline() cache.Pipeliner {
 | |
| 	p := r.client.Pipeline()
 | |
| 	return &pipelineImpl{p: p}
 | |
| }
 | |
| 
 | |
| // RPush implements cache.Cmdable.
 | |
| func (r *redisImpl) RPush(ctx context.Context, key string, values ...interface{}) cache.IntCmd {
 | |
| 	return r.client.RPush(ctx, key, values...)
 | |
| }
 | |
| 
 | |
| // Set implements cache.Cmdable.
 | |
| func (r *redisImpl) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) cache.StatusCmd {
 | |
| 	return r.client.Set(ctx, key, value, expiration)
 | |
| }
 | |
| 
 | |
| type pipelineImpl struct {
 | |
| 	p redis.Pipeliner
 | |
| }
 | |
| 
 | |
| // Del implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Del(ctx context.Context, keys ...string) cache.IntCmd {
 | |
| 	return p.p.Del(ctx, keys...)
 | |
| }
 | |
| 
 | |
| // Exec implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Exec(ctx context.Context) ([]cache.Cmder, error) {
 | |
| 	cmders, err := p.p.Exec(ctx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return convertCmders(cmders), nil
 | |
| }
 | |
| 
 | |
| func convertCmders(cmders []redis.Cmder) []cache.Cmder {
 | |
| 	res := make([]cache.Cmder, 0, len(cmders))
 | |
| 	for _, cmder := range cmders {
 | |
| 		res = append(res, &cmderImpl{cmder: cmder})
 | |
| 	}
 | |
| 	return res
 | |
| }
 | |
| 
 | |
| type cmderImpl struct {
 | |
| 	cmder redis.Cmder
 | |
| }
 | |
| 
 | |
| func (c *cmderImpl) Err() error {
 | |
| 	return c.cmder.Err()
 | |
| }
 | |
| 
 | |
| // Exists implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Exists(ctx context.Context, keys ...string) cache.IntCmd {
 | |
| 	return p.p.Exists(ctx, keys...)
 | |
| }
 | |
| 
 | |
| // Expire implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Expire(ctx context.Context, key string, expiration time.Duration) cache.BoolCmd {
 | |
| 	return p.p.Expire(ctx, key, expiration)
 | |
| }
 | |
| 
 | |
| // Get implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Get(ctx context.Context, key string) cache.StringCmd {
 | |
| 	return p.p.Get(ctx, key)
 | |
| }
 | |
| 
 | |
| // HGetAll implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) HGetAll(ctx context.Context, key string) cache.MapStringStringCmd {
 | |
| 	return p.p.HGetAll(ctx, key)
 | |
| }
 | |
| 
 | |
| // HSet implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) HSet(ctx context.Context, key string, values ...interface{}) cache.IntCmd {
 | |
| 	return p.p.HSet(ctx, key, values...)
 | |
| }
 | |
| 
 | |
| // Incr implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Incr(ctx context.Context, key string) cache.IntCmd {
 | |
| 	return p.p.Incr(ctx, key)
 | |
| }
 | |
| 
 | |
| // IncrBy implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) IncrBy(ctx context.Context, key string, value int64) cache.IntCmd {
 | |
| 	return p.p.IncrBy(ctx, key, value)
 | |
| }
 | |
| 
 | |
| // LIndex implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) LIndex(ctx context.Context, key string, index int64) cache.StringCmd {
 | |
| 	return p.p.LIndex(ctx, key, index)
 | |
| }
 | |
| 
 | |
| // LPop implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) LPop(ctx context.Context, key string) cache.StringCmd {
 | |
| 	return p.p.LPop(ctx, key)
 | |
| }
 | |
| 
 | |
| // LPush implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) LPush(ctx context.Context, key string, values ...interface{}) cache.IntCmd {
 | |
| 	return p.p.LPush(ctx, key, values...)
 | |
| }
 | |
| 
 | |
| // LRange implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) LRange(ctx context.Context, key string, start int64, stop int64) cache.StringSliceCmd {
 | |
| 	return p.p.LRange(ctx, key, start, stop)
 | |
| }
 | |
| 
 | |
| // LSet implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) LSet(ctx context.Context, key string, index int64, value interface{}) cache.StatusCmd {
 | |
| 	return p.p.LSet(ctx, key, index, value)
 | |
| }
 | |
| 
 | |
| // Pipeline implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Pipeline() cache.Pipeliner {
 | |
| 	return p
 | |
| }
 | |
| 
 | |
| // RPush implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) RPush(ctx context.Context, key string, values ...interface{}) cache.IntCmd {
 | |
| 	return p.p.RPush(ctx, key, values...)
 | |
| }
 | |
| 
 | |
| // Set implements cache.Pipeliner.
 | |
| func (p *pipelineImpl) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) cache.StatusCmd {
 | |
| 	return p.p.Set(ctx, key, value, expiration)
 | |
| }
 |