Skip to content

Commit 4613c40

Browse files
committed
fix: close
1 parent a07b776 commit 4613c40

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

modules/globallock/globallock_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,25 @@ func TestLockAndDo(t *testing.T) {
2525
}
2626
}
2727

28+
oldDefaultLocker := defaultLocker
29+
defer func() {
30+
defaultLocker = oldDefaultLocker
31+
}()
32+
2833
initOnce = sync.Once{}
2934
initFunc = func() {
3035
defaultLocker = NewRedisLocker(url)
3136
}
3237

3338
testLockAndDo(t)
39+
require.NoError(t, defaultLocker.(*redisLocker).Close())
3440
})
3541
t.Run("memory", func(t *testing.T) {
42+
oldDefaultLocker := defaultLocker
43+
defer func() {
44+
defaultLocker = oldDefaultLocker
45+
}()
46+
3647
initOnce = sync.Once{}
3748
initFunc = func() {
3849
defaultLocker = NewMemoryLocker()

modules/globallock/locker_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func TestLocker(t *testing.T) {
3535
locker := NewRedisLocker(url)
3636
testLocker(t, locker)
3737
testRedisLocker(t, locker.(*redisLocker))
38+
require.NoError(t, locker.(*redisLocker).Close())
3839
})
3940
t.Run("memory", func(t *testing.T) {
4041
locker := NewMemoryLocker()
@@ -178,7 +179,17 @@ func testMemoryLocker(t *testing.T, locker *memoryLocker) {
178179

179180
// testRedisLocker does specific tests for redisLocker
180181
func testRedisLocker(t *testing.T, locker *redisLocker) {
181-
t.Run("missing extension", func(t *testing.T) {
182+
defer func() {
183+
// This case should be tested at the end.
184+
// Otherwise, it will affect other tests.
185+
t.Run("close", func(t *testing.T) {
186+
assert.NoError(t, locker.Close())
187+
_, _, err := locker.Lock(context.Background(), "test")
188+
assert.Error(t, err)
189+
})
190+
}()
191+
192+
t.Run("failed extend", func(t *testing.T) {
182193
ctx, release, err := locker.Lock(context.Background(), "test")
183194
defer release()
184195
require.NoError(t, err)

modules/globallock/redis_locker.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ package globallock
66
import (
77
"context"
88
"errors"
9+
"fmt"
910
"sync"
11+
"sync/atomic"
1012
"time"
1113

1214
"code.gitea.io/gitea/modules/nosql"
@@ -25,6 +27,7 @@ type redisLocker struct {
2527
rs *redsync.Redsync
2628

2729
mutexM sync.Map
30+
closed atomic.Bool
2831
}
2932

3033
var _ Locker = &redisLocker{}
@@ -59,12 +62,25 @@ func (l *redisLocker) TryLock(ctx context.Context, key string) (bool, context.Co
5962
return err == nil, ctx, f, err
6063
}
6164

65+
// Close closes the locker.
66+
// It will stop extending the locks and refuse to acquire new locks.
67+
// In actual use, it is not necessary to call this function.
68+
// But it's useful in tests to release resources.
69+
func (l *redisLocker) Close() error {
70+
l.closed.Store(true)
71+
return nil
72+
}
73+
6274
type redisMutex struct {
6375
mutex *redsync.Mutex
6476
cancel context.CancelCauseFunc
6577
}
6678

6779
func (l *redisLocker) lock(ctx context.Context, key string, tries int) (context.Context, ReleaseFunc, error) {
80+
if l.closed.Load() {
81+
return ctx, func() context.Context { return ctx }, fmt.Errorf("locker is closed")
82+
}
83+
6884
originalCtx := ctx
6985

7086
options := []redsync.Option{
@@ -102,6 +118,10 @@ func (l *redisLocker) lock(ctx context.Context, key string, tries int) (context.
102118
}
103119

104120
func (l *redisLocker) startExtend() {
121+
if l.closed.Load() {
122+
return
123+
}
124+
105125
toExtend := make([]*redisMutex, 0)
106126
l.mutexM.Range(func(_, value any) bool {
107127
m := value.(*redisMutex)

0 commit comments

Comments
 (0)