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