Skip to content

Commit

Permalink
feat:update ttl to ms (#35)
Browse files Browse the repository at this point in the history
* feat:update ttl to ms

* test:update ut
  • Loading branch information
qinguoyi authored Aug 24, 2024
1 parent 64fbea9 commit cafcdf5
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 47 deletions.
4 changes: 2 additions & 2 deletions lock_redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var (

// Lock 加锁
func (lock *RedisLock) Lock() error {
result, err := lock.redis.Eval(lock.Context, reentrantLockScript, []string{lock.key}, lock.token, lock.lockTimeout.Seconds()).Result()
result, err := lock.redis.Eval(lock.Context, reentrantLockScript, []string{lock.key}, lock.token, lock.lockTimeout.Milliseconds()).Result()

if err != nil {
return ErrException
Expand Down Expand Up @@ -79,7 +79,7 @@ func (lock *RedisLock) SpinLock(timeout time.Duration) error {

// Renew 锁手动续期
func (lock *RedisLock) Renew() error {
res, err := lock.redis.Eval(lock.Context, reentrantRenewScript, []string{lock.key}, lock.token, lock.lockTimeout.Seconds()).Result()
res, err := lock.redis.Eval(lock.Context, reentrantRenewScript, []string{lock.key}, lock.token, lock.lockTimeout.Milliseconds()).Result()

if err != nil {
return ErrException
Expand Down
32 changes: 16 additions & 16 deletions lock_redis_local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestLockSuccess(t *testing.T) {
lock := New(ctx, db, key, WithToken(token))

// 设置模拟锁获取成功的行为
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

err := lock.Lock()
if err != nil {
Expand All @@ -53,7 +53,7 @@ func TestLockFail(t *testing.T) {

ctx := context.Background()
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestUnlockFail(t *testing.T) {
lock := New(ctx, db, key, WithToken(token))

// 加锁逻辑
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

err := lock.Lock()
if err != nil {
Expand Down Expand Up @@ -142,8 +142,8 @@ func TestSpinLockSuccess(t *testing.T) {
token2 := "some_token2"
spinTimeout := time.Duration(5) * time.Second

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Milliseconds()).SetVal("OK")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -192,8 +192,8 @@ func TestSpinLockTimeout(t *testing.T) {
spinTimeout := time.Duration(5) * time.Second
spinTimeout2 := time.Duration(3) * time.Second

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Seconds()).SetVal("nil")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Milliseconds()).SetVal("nil")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -238,8 +238,8 @@ func TestRenewSuccess(t *testing.T) {
key := "test_key_TestRenewSuccess"
token := "some_token"

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

// 设置模拟锁续期成功的行为
mock.ExpectExpire(key, lockTime).SetVal(true)
Expand Down Expand Up @@ -283,7 +283,7 @@ func TestRenewFail(t *testing.T) {
key := "test_key_TestRenewFail"
token := "some_token"

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
// 设置模拟锁续期成功的行为
mock.ExpectExpire(key, lockTime).SetVal(false)

Expand Down Expand Up @@ -328,7 +328,7 @@ func TestWithTimeout(t *testing.T) {
token := "some_token"
timeout := time.Duration(10) * time.Second

mock.ExpectEval(reentrantLockScript, []string{key}, token, timeout.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, timeout.Milliseconds()).SetVal("OK")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -375,8 +375,8 @@ func TestAutoRenew(t *testing.T) {
key := "test_key_TestAutoRenew"
token := "some_token"

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectExpire(key, lockTime).SetVal(true)

lock := New(ctx, db, key, WithToken(token), WithAutoRenew())
Expand All @@ -400,7 +400,7 @@ func TestAutoRenew(t *testing.T) {
// token := "some_token"
//
// // 设置模拟锁获取成功的行为
// mock.ExpectEval(lockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
// mock.ExpectEval(lockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
// // 设置模拟锁续期成功的行为
// mock.ExpectExpire(key, lockTime).SetVal(true)
//
Expand All @@ -414,7 +414,7 @@ func TestAutoRenew(t *testing.T) {
// go func() {
// defer wg.Done()
// // 模拟锁续期成功
// mock.ExpectEval(renewScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
// mock.ExpectEval(renewScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
// // 等待一段时间,模拟自动续期的过程
// time.Sleep(time.Second * 3)
// // 取消上下文,模拟上下文的取消
Expand Down Expand Up @@ -515,7 +515,7 @@ func TestSevLockSuccess(t *testing.T) {
lock := New(ctx, redisClient, key)

times, _ := redisClient.TTL(ctx, key).Result()
log.Println("线程二:ttl 时间:", times.Seconds())
log.Println("线程二:ttl 时间:", times.Milliseconds())

err := lock.Lock()
if err == nil {
Expand Down
46 changes: 23 additions & 23 deletions lock_redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestRedisLock_Lock(t *testing.T) {
name: "加锁成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -34,7 +34,7 @@ func TestRedisLock_Lock(t *testing.T) {
name: "加锁内部异常",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetErr(ErrException)
return db
},
Expand All @@ -46,7 +46,7 @@ func TestRedisLock_Lock(t *testing.T) {
name: "加锁失败",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("nil")
return db
},
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestRedisLock_UnLock(t *testing.T) {
name: "解锁成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantUnLockScript, []string{"key"}, "token").
SetVal("OK")
Expand All @@ -99,7 +99,7 @@ func TestRedisLock_UnLock(t *testing.T) {
name: "解锁内部异常",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantUnLockScript, []string{"key"}, "token").
SetErr(ErrException)
Expand All @@ -119,7 +119,7 @@ func TestRedisLock_UnLock(t *testing.T) {
name: "解锁失败",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantUnLockScript, []string{"key"}, "token").
SetVal("nil")
Expand Down Expand Up @@ -166,7 +166,7 @@ func TestRedisLock_SpinLock(t *testing.T) {
name: "自旋锁-加锁成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -185,7 +185,7 @@ func TestRedisLock_SpinLock(t *testing.T) {
name: "自旋锁-加锁超时",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -210,7 +210,7 @@ func TestRedisLock_SpinLock(t *testing.T) {
name: "自旋锁-Ctx取消",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand Down Expand Up @@ -267,9 +267,9 @@ func TestRedisLock_LockRenew(t *testing.T) {
name: "锁手动续期成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -287,9 +287,9 @@ func TestRedisLock_LockRenew(t *testing.T) {
name: "锁手动续期异常",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetErr(ErrException)
return db
},
Expand All @@ -307,9 +307,9 @@ func TestRedisLock_LockRenew(t *testing.T) {
name: "锁手动续期失败",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("nil")
return db
},
Expand Down Expand Up @@ -362,9 +362,9 @@ func TestRedisLock_LockAutoRenew(t *testing.T) {
name: "锁自动续期成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -382,9 +382,9 @@ func TestRedisLock_LockAutoRenew(t *testing.T) {
name: "锁自动续期-Ctx取消",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand Down Expand Up @@ -440,10 +440,10 @@ func TestRedisLock_LockTimeout(t *testing.T) {
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
// 第一次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Milliseconds()).
SetVal("OK")
// 第二次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Milliseconds()).
SetVal("OK")

// 第一次解锁
Expand Down Expand Up @@ -476,10 +476,10 @@ func TestRedisLock_LockTimeout(t *testing.T) {
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
// 第一次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Milliseconds()).
SetVal("OK")
// 第二次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Milliseconds()).
SetVal("nil")

// 第一次解锁
Expand Down
8 changes: 4 additions & 4 deletions lua/reentrantLock.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ local reentrant_count = tonumber(redis.call('GET', reentrant_key) or '0')
-- 可重入锁计数器
if reentrant_count > 0 then
redis.call('INCR', reentrant_key)
redis.call('EXPIRE', lock_key, lock_ttl)
redis.call('EXPIRE', reentrant_key, lock_ttl)
redis.call('PEXPIRE', lock_key, lock_ttl)
redis.call('PEXPIRE', reentrant_key, lock_ttl)
return "OK"
end

-- 创建锁
if redis.call('SET', lock_key, lock_value, 'NX', 'EX', lock_ttl) then
if redis.call('SET', lock_key, lock_value, 'NX', 'PX', lock_ttl) then
redis.call('SET', reentrant_key, 1)
redis.call('EXPIRE', reentrant_key, lock_ttl)
redis.call('PEXPIRE', reentrant_key, lock_ttl)
return "OK"
end

Expand Down
4 changes: 2 additions & 2 deletions lua/reentrantRenew.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ local reentrant_count = tonumber(redis.call('GET', reentrant_key) or '0')
-- 重入锁的场景(reentrant_count > 0)
-- 普通锁的场景(redis.call('GET', lock_key) == lock_value)
if reentrant_count > 0 or redis.call('GET', lock_key) == lock_value then
redis.call('EXPIRE', lock_key, lock_ttl)
redis.call('EXPIRE', reentrant_key, lock_ttl)
redis.call('PEXPIRE', lock_key, lock_ttl)
redis.call('PEXPIRE', reentrant_key, lock_ttl)
return "OK"
end

Expand Down

0 comments on commit cafcdf5

Please sign in to comment.