feat(redislock): support set context (#2208)

* feat(redislock): support set context

* chore: fix test
master
cong 2 years ago committed by GitHub
parent b18479dd43
commit 4879d4dfcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,12 +1,14 @@
package redis package redis
import ( import (
"context"
"math/rand" "math/rand"
"strconv" "strconv"
"sync/atomic" "sync/atomic"
"time" "time"
red "github.com/go-redis/redis/v8" red "github.com/go-redis/redis/v8"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
) )
@ -34,6 +36,7 @@ type RedisLock struct {
seconds uint32 seconds uint32
key string key string
id string id string
ctx context.Context
} }
func init() { func init() {
@ -51,8 +54,9 @@ func NewRedisLock(store *Redis, key string) *RedisLock {
// Acquire acquires the lock. // Acquire acquires the lock.
func (rl *RedisLock) Acquire() (bool, error) { func (rl *RedisLock) Acquire() (bool, error) {
rl.fillCtx()
seconds := atomic.LoadUint32(&rl.seconds) seconds := atomic.LoadUint32(&rl.seconds)
resp, err := rl.store.Eval(lockCommand, []string{rl.key}, []string{ resp, err := rl.store.EvalCtx(rl.ctx, lockCommand, []string{rl.key}, []string{
rl.id, strconv.Itoa(int(seconds)*millisPerSecond + tolerance), rl.id, strconv.Itoa(int(seconds)*millisPerSecond + tolerance),
}) })
if err == red.Nil { if err == red.Nil {
@ -75,7 +79,8 @@ func (rl *RedisLock) Acquire() (bool, error) {
// Release releases the lock. // Release releases the lock.
func (rl *RedisLock) Release() (bool, error) { func (rl *RedisLock) Release() (bool, error) {
resp, err := rl.store.Eval(delCommand, []string{rl.key}, []string{rl.id}) rl.fillCtx()
resp, err := rl.store.EvalCtx(rl.ctx, delCommand, []string{rl.key}, []string{rl.id})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -92,3 +97,14 @@ func (rl *RedisLock) Release() (bool, error) {
func (rl *RedisLock) SetExpire(seconds int) { func (rl *RedisLock) SetExpire(seconds int) {
atomic.StoreUint32(&rl.seconds, uint32(seconds)) atomic.StoreUint32(&rl.seconds, uint32(seconds))
} }
// WithContext set context.
func (rl *RedisLock) WithContext(ctx context.Context) {
rl.ctx = ctx
}
func (rl *RedisLock) fillCtx() {
if rl.ctx == nil {
rl.ctx = context.Background()
}
}

@ -1,22 +1,31 @@
package redis package redis
import ( import (
"context"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
) )
func TestRedisLock(t *testing.T) { func TestRedisLock(t *testing.T) {
runOnRedis(t, func(client *Redis) { testFn := func(ctx context.Context) func(client *Redis) {
return func(client *Redis) {
key := stringx.Rand() key := stringx.Rand()
firstLock := NewRedisLock(client, key) firstLock := NewRedisLock(client, key)
if ctx != nil {
firstLock.WithContext(ctx)
}
firstLock.SetExpire(5) firstLock.SetExpire(5)
firstAcquire, err := firstLock.Acquire() firstAcquire, err := firstLock.Acquire()
assert.Nil(t, err) assert.Nil(t, err)
assert.True(t, firstAcquire) assert.True(t, firstAcquire)
secondLock := NewRedisLock(client, key) secondLock := NewRedisLock(client, key)
if ctx != nil {
secondLock.WithContext(ctx)
}
secondLock.SetExpire(5) secondLock.SetExpire(5)
againAcquire, err := secondLock.Acquire() againAcquire, err := secondLock.Acquire()
assert.Nil(t, err) assert.Nil(t, err)
@ -29,5 +38,14 @@ func TestRedisLock(t *testing.T) {
endAcquire, err := secondLock.Acquire() endAcquire, err := secondLock.Acquire()
assert.Nil(t, err) assert.Nil(t, err)
assert.True(t, endAcquire) assert.True(t, endAcquire)
}
}
t.Run("normal", func(t *testing.T) {
runOnRedis(t, testFn(nil))
})
t.Run("withContext", func(t *testing.T) {
runOnRedis(t, testFn(context.Background()))
}) })
} }

Loading…
Cancel
Save