machinery icon indicating copy to clipboard operation
machinery copied to clipboard

redis.Lock bug

Open huyidaoxinyu opened this issue 2 years ago • 0 comments

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
}

huyidaoxinyu avatar Aug 02 '22 04:08 huyidaoxinyu