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.
ims/util/cache/cache.go

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))
}