Skip to content

Commit b0b5e0b

Browse files
committed
feat - add candiutils redis locker with options
1 parent 344c0b2 commit b0b5e0b

File tree

7 files changed

+58
-45
lines changed

7 files changed

+58
-45
lines changed

candiutils/locker.go

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"time"
88

9+
"github.com/golangid/candi/options"
910
"github.com/gomodule/redigo/redis"
1011
)
1112

@@ -15,39 +16,37 @@ type (
1516
// RedisLocker lock using redis
1617
RedisLocker struct {
1718
pool *redis.Pool
18-
lockeroptions LockerOptions
19+
lockeroptions options.LockerOptions
1920
}
2021

2122
// NoopLocker empty locker
2223
NoopLocker struct{}
23-
24-
// Options for RedisLocker
25-
LockerOptions struct {
26-
Prefix string
27-
TTL time.Duration
28-
}
29-
30-
// Option function type for setting options
31-
LockerOption func(*LockerOptions)
3224
)
3325

3426
// WithPrefix sets the prefix for keys
35-
func WithPrefixLocker(prefix string) LockerOption {
36-
return func(o *LockerOptions) {
27+
func WithPrefixLocker(prefix string) options.LockerOption {
28+
return func(o *options.LockerOptions) {
3729
o.Prefix = prefix
3830
}
3931
}
4032

4133
// WithTTL sets the default TTL for keys
42-
func WithTTLLocker(ttl time.Duration) LockerOption {
43-
return func(o *LockerOptions) {
34+
func WithTTLLocker(ttl time.Duration) options.LockerOption {
35+
return func(o *options.LockerOptions) {
4436
o.TTL = ttl
4537
}
4638
}
4739

40+
// WithLimit sets the limit for keys
41+
func WithLimitLocker(limit int) options.LockerOption {
42+
return func(o *options.LockerOptions) {
43+
o.Limit = limit
44+
}
45+
}
46+
4847
// NewRedisLocker constructor
49-
func NewRedisLocker(pool *redis.Pool, opts ...LockerOption) *RedisLocker {
50-
lockeroptions := LockerOptions{
48+
func NewRedisLocker(pool *redis.Pool, opts ...options.LockerOption) *RedisLocker {
49+
lockeroptions := options.LockerOptions{
5150
Prefix: "LOCKFOR",
5251
TTL: 0,
5352
}
@@ -104,31 +103,26 @@ func (r *RedisLocker) IsLockedTTL(key string, TTL time.Duration) bool {
104103
return incr > 1
105104
}
106105

107-
// IsLockedTTLWithLimit checks if the key has been incremented more than the specified limit
108-
// within the given TTL. If the key is being created for the first time, it sets the TTL.
109-
// Example usage: check if a key has been incremented more than 10 times within 1 minute.
110-
func (r *RedisLocker) IsLockedTTLWithLimit(key string, limit int, TTL time.Duration) bool {
106+
func (r *RedisLocker) IsLockedWithOpts(key string, opts ...options.LockerOption) bool {
111107
conn := r.pool.Get()
112108
defer conn.Close()
113109

110+
lockOpt := r.lockeroptions
111+
for _, opt := range opts {
112+
opt(&lockOpt)
113+
}
114+
114115
lockKey := fmt.Sprintf("%s:%s", r.lockeroptions.Prefix, key)
115116
incr, err := redis.Int64(conn.Do("INCR", lockKey))
116117
if err != nil {
117118
return false
118119
}
119120

120-
var expireTime time.Duration
121-
if TTL > 0 {
122-
expireTime = TTL
123-
} else {
124-
expireTime = r.lockeroptions.TTL
125-
}
126-
127-
if expireTime > 0 && incr == 1 {
128-
conn.Do("EXPIRE", lockKey, int(expireTime.Seconds()))
121+
withLimit := lockOpt.Limit > 1
122+
if lockOpt.TTL > 0 && !(withLimit && incr == 1) {
123+
conn.Do("EXPIRE", lockKey, int(lockOpt.TTL.Seconds()))
129124
}
130-
131-
return incr > int64(limit)
125+
return incr > int64(lockOpt.Limit)
132126
}
133127

134128
func (r *RedisLocker) HasBeenLocked(key string) bool {
@@ -242,6 +236,9 @@ func (NoopLocker) IsLocked(string) bool { return false }
242236
// IsLockedTTL method
243237
func (NoopLocker) IsLockedTTL(string, time.Duration) bool { return false }
244238

239+
// IsLockedWithOpts method
240+
func (NoopLocker) IsLockedWithOpts(string, ...options.LockerOption) bool { return false }
241+
245242
// HasBeenLocked method
246243
func (NoopLocker) HasBeenLocked(string) bool { return false }
247244

@@ -254,13 +251,10 @@ func (NoopLocker) Reset(string) {}
254251
// Lock method
255252
func (NoopLocker) Lock(string, time.Duration) (func(), error) { return func() {}, nil }
256253

257-
func (NoopLocker) Disconnect(context.Context) error { return nil }
258-
259254
// GetPrefix method
260255
func (NoopLocker) GetPrefixLocker() string { return "" }
261256

262257
// GetTTLLocker method
263258
func (NoopLocker) GetTTLLocker() time.Duration { return 0 }
264259

265-
// IsLockedTTLWithLimit method
266-
func (NoopLocker) IsLockedTTLWithLimit(string, int, time.Duration) bool { return false }
260+
func (NoopLocker) Disconnect(context.Context) error { return nil }

codebase/interfaces/locker.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
package interfaces
22

3-
import "time"
3+
import (
4+
"time"
5+
6+
"github.com/golangid/candi/options"
7+
)
48

59
type (
610
// Locker abstraction, lock concurrent process
711
Locker interface {
812
IsLocked(key string) bool
913
IsLockedTTL(key string, ttl time.Duration) bool
14+
IsLockedWithOpts(key string, opts ...options.LockerOption) bool
1015
HasBeenLocked(key string) bool
1116
Unlock(key string)
1217
Reset(key string)
1318
Lock(key string, timeout time.Duration) (unlockFunc func(), err error)
1419
GetPrefixLocker() string
1520
GetTTLLocker() time.Duration
16-
IsLockedTTLWithLimit(key string, limit int, TTL time.Duration) bool
1721
Closer
1822
}
1923
)

mocks/candiutils/HTTPRequest.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mocks/candiutils/WorkerPool.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mocks/candiutils/cronparser/Schedule.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mocks/candiutils/LockerOption.go renamed to mocks/options/LockerOption.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

options/locker.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package options
2+
3+
import "time"
4+
5+
type (
6+
// Options for RedisLocker
7+
LockerOptions struct {
8+
Prefix string
9+
TTL time.Duration
10+
Limit int
11+
}
12+
13+
// Option function type for setting options
14+
LockerOption func(*LockerOptions)
15+
)

0 commit comments

Comments
 (0)