You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.1 KiB
100 lines
2.1 KiB
package cache
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"ims/util/rdb"
|
|
|
|
"github.com/go-redis/cache/v9"
|
|
"github.com/redis/go-redis/v9"
|
|
"golang.org/x/sync/singleflight"
|
|
"zestack.dev/env"
|
|
)
|
|
|
|
var (
|
|
engine *cache.Cache
|
|
sfg singleflight.Group
|
|
|
|
ErrCacheMiss = cache.ErrCacheMiss
|
|
)
|
|
|
|
func Init() error {
|
|
engine = cache.New(&cache.Options{
|
|
Redis: rdb.Redis(),
|
|
LocalCache: cache.NewTinyLFU(1000, time.Minute),
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func realKey(key string) string {
|
|
return fmt.Sprintf("%s:%s", env.String("CACHE_PREFIX", "cache"), key)
|
|
}
|
|
|
|
func Get(ctx context.Context, key string, value any) error {
|
|
return engine.Get(ctx, realKey(key), value)
|
|
}
|
|
|
|
func GetOr(ctx context.Context, key string, value any, or func(ctx context.Context, key string, value any) error) error {
|
|
_, err, _ := sfg.Do(key, func() (interface{}, error) {
|
|
err := engine.Get(ctx, realKey(key), value)
|
|
if err == nil {
|
|
return nil, nil
|
|
}
|
|
if errors.Is(err, cache.ErrCacheMiss) {
|
|
err = or(ctx, key, value)
|
|
if err == nil {
|
|
_ = Set(ctx, key, value)
|
|
}
|
|
}
|
|
if errors.Is(err, redis.Nil) {
|
|
return nil, ErrCacheMiss
|
|
}
|
|
return nil, err
|
|
})
|
|
|
|
return err
|
|
}
|
|
|
|
// Set 设置缓存 默认 1 小时有效
|
|
func Set(ctx context.Context, key string, value any) error {
|
|
return engine.Set(&cache.Item{
|
|
Ctx: ctx,
|
|
Key: realKey(key),
|
|
Value: value,
|
|
TTL: env.Duration("CACHE_TTL", time.Hour),
|
|
})
|
|
}
|
|
|
|
// SetNX only sets the key if it does not already exist.
|
|
func SetNX(ctx context.Context, key string, value any) error {
|
|
return engine.Set(&cache.Item{
|
|
Ctx: ctx,
|
|
Key: realKey(key),
|
|
Value: value,
|
|
TTL: env.Duration("CACHE_TTL", time.Hour),
|
|
SetNX: true,
|
|
})
|
|
}
|
|
|
|
// SetXX only sets the key if it already exists.
|
|
func SetXX(ctx context.Context, key string, value any) error {
|
|
return engine.Set(&cache.Item{
|
|
Ctx: ctx,
|
|
Key: realKey(key),
|
|
Value: value,
|
|
TTL: env.Duration("CACHE_TTL", time.Hour),
|
|
SetXX: true,
|
|
})
|
|
}
|
|
|
|
func Exists(ctx context.Context, key string) bool {
|
|
return engine.Exists(ctx, realKey(key))
|
|
}
|
|
|
|
func Delete(ctx context.Context, key string) error {
|
|
return engine.Delete(ctx, realKey(key))
|
|
}
|
|
|