machinery
machinery copied to clipboard
redis.Lock bug
I found a bug in the function of struct redis.Lock in v2/locks/redis/redis.go file. if the key not expired when r.rclient.Get,but expired when r.rclient.GetSet, it will lock failed. My fix codes like this:
func (r Lock) Lock(key string, unixTsToExpireNs int64) error {
now := time.Now().UnixNano()
expiration := time.Duration(unixTsToExpireNs + 1 - now)
ctx := r.rclient.Context()
success, err := r.rclient.SetNX(ctx, key, unixTsToExpireNs, expiration).Result()
if err != nil {
return err
}
if !success {
v, err := r.rclient.Get(ctx, key).Result()
if err != nil {
return err
}
timeout, err := strconv.Atoi(v)
if err != nil {
return err
}
if timeout != 0 && now > int64(timeout) {
newTimeout, err := r.rclient.GetSet(ctx, key, unixTsToExpireNs).Result()
if err != nil&& err != redis.Nil {
return err
}
curTimeout := 0
if newTimeout != "" {
curTimeout, err := strconv.Atoi(newTimeout)
if err != nil {
return err
}
}
if now > int64(curTimeout) {
// success to acquire lock with get set
// set the expiration of redis key
r.rclient.Expire(ctx, key, expiration)
return nil
}
return ErrRedisLockFailed
}
return ErrRedisLockFailed
}
return nil
}