package lockdo import ( "context" "joybuywork/internal/app" "joybuywork/internal/consts/ckey" "joybuywork/proto/go_proto/workerr" "errors" "math/rand" "time" grds "github.com/go-redis/redis/v8" ) func Int64(ctx context.Context, key string, find func() (num int64, err error)) (num int64, err error) { num, err = app.Redis.Cache.Get(ctx, key).Int64() if !errors.Is(err, grds.Nil) { if err != nil { return } return num, nil } lc := app.NewFollower(ctx, ckey.ForLock(key)).Lock() defer lc.Release() if lc.Error() != nil { err = workerr.BusyError return } num, err = app.Redis.Cache.Get(ctx, key).Int64() if !errors.Is(err, grds.Nil) { if err != nil { return } return num, nil } num, err = find() if err != nil { return } app.Redis.Cache.IncrBy(ctx, key, num) app.Redis.Cache.Expire(ctx, key, Rand2HourExp()) return } func Bytes(ctx context.Context, key string, find func() (data []byte, err error)) (data []byte, err error) { data, err = app.Redis.Cache.Get(ctx, key).Bytes() if !errors.Is(err, grds.Nil) { if err != nil { return } return data, nil } lc := app.NewFollower(ctx, ckey.ForLock(key)).Lock() defer lc.Release() if lc.Error() != nil { err = workerr.BusyError return } data, err = app.Redis.Cache.Get(ctx, key).Bytes() if !errors.Is(err, grds.Nil) { if err != nil { return } return data, nil } data, err = find() if err != nil { return } app.Redis.Cache.Set(ctx, key, data, Rand2HourExp()) return } // ExistDo Key如果存在就返回,不存在就锁住做一些操作 func ExistDo(ctx context.Context, key string, fn func(exist bool) (err error)) (err error) { exist, err := app.Redis.Exists(ctx, key) if err != nil { return } if exist { return fn(true) } lc := app.NewFollower(ctx, ckey.ForLock(key)).Lock() defer lc.Release() if lc.Error() != nil { err = workerr.BusyError return } exist, err = app.Redis.Exists(ctx, key) if err != nil { return } return fn(exist) } func FindNilDo(ctx context.Context, key string, find func() (none bool, err error), create func() (err error)) (err error) { none, err := find() if err != nil { return } if !none { return } lc := app.NewFollower(ctx, ckey.ForLock(key)).Lock() defer lc.Release() if lc.Error() != nil { err = workerr.BusyError return } none, err = find() if err != nil { return } if !none { return } return create() } func Rand2HourExp() time.Duration { return time.Duration(rand.Intn(60)+60) * time.Minute }