@@ -29,16 +29,16 @@ func NewLimiter(redis rediser) *Limiter {
29
29
}
30
30
}
31
31
32
- // Reset resets the rate limit for the name in the given rate limit window .
33
- func (l * Limiter ) Reset (name string , dur time.Duration ) error {
34
- udur := int64 (dur / time .Second )
35
- slot := time .Now ().Unix () / udur
32
+ // Reset resets the rate limit for the name in the given rate limit period .
33
+ func (l * Limiter ) Reset (name string , period time.Duration ) error {
34
+ secs := int64 (period / time .Second )
35
+ slot := time .Now ().Unix () / secs
36
36
37
37
name = allowName (name , slot )
38
38
return l .redis .Del (name ).Err ()
39
39
}
40
40
41
- // Reset resets the rate limit for the name and limit.
41
+ // ResetRate resets the rate limit for the name and limit.
42
42
func (l * Limiter ) ResetRate (name string , rateLimit rate.Limit ) error {
43
43
if rateLimit == 0 {
44
44
return nil
@@ -47,45 +47,40 @@ func (l *Limiter) ResetRate(name string, rateLimit rate.Limit) error {
47
47
return nil
48
48
}
49
49
50
- dur := time .Second
51
- limit := int64 (rateLimit )
52
- if limit == 0 {
53
- limit = 1
54
- dur *= time .Duration (1 / rateLimit )
55
- }
56
- slot := time .Now ().UnixNano () / dur .Nanoseconds ()
50
+ _ , period := limitPeriod (rateLimit )
51
+ slot := time .Now ().UnixNano () / period .Nanoseconds ()
57
52
58
- name = allowRateName (name , dur , slot )
53
+ name = allowRateName (name , period , slot )
59
54
return l .redis .Del (name ).Err ()
60
55
}
61
56
62
57
// AllowN reports whether an event with given name may happen at time now.
63
- // It allows up to maxn events within duration dur , with each interaction
58
+ // It allows up to maxn events within period , with each interaction
64
59
// incrementing the limit by n.
65
60
func (l * Limiter ) AllowN (
66
- name string , maxn int64 , dur time.Duration , n int64 ,
61
+ name string , maxn int64 , period time.Duration , n int64 ,
67
62
) (count int64 , delay time.Duration , allow bool ) {
68
- udur := int64 (dur / time .Second )
63
+ secs := int64 (period / time .Second )
69
64
utime := time .Now ().Unix ()
70
- slot := utime / udur
71
- delay = time .Duration ((slot + 1 )* udur - utime ) * time .Second
65
+ slot := utime / secs
66
+ delay = time .Duration ((slot + 1 )* secs - utime ) * time .Second
72
67
73
68
if l .Fallback != nil {
74
69
allow = l .Fallback .Allow ()
75
70
}
76
71
77
72
name = allowName (name , slot )
78
- count , err := l .incr (name , dur , n )
73
+ count , err := l .incr (name , period , n )
79
74
if err == nil {
80
75
allow = count <= maxn
81
76
}
82
77
83
78
return count , delay , allow
84
79
}
85
80
86
- // Allow is shorthand for AllowN(name, max, dur , 1).
87
- func (l * Limiter ) Allow (name string , maxn int64 , dur time.Duration ) (count int64 , delay time.Duration , allow bool ) {
88
- return l .AllowN (name , maxn , dur , 1 )
81
+ // Allow is shorthand for AllowN(name, max, period , 1).
82
+ func (l * Limiter ) Allow (name string , maxn int64 , period time.Duration ) (count int64 , delay time.Duration , allow bool ) {
83
+ return l .AllowN (name , maxn , period , 1 )
89
84
}
90
85
91
86
// AllowMinute is shorthand for Allow(name, maxn, time.Minute).
@@ -108,37 +103,41 @@ func (l *Limiter) AllowRate(name string, rateLimit rate.Limit) (delay time.Durat
108
103
return 0 , true
109
104
}
110
105
111
- dur := time .Second
112
- limit := int64 (rateLimit )
113
- if limit == 0 {
114
- limit = 1
115
- dur *= time .Duration (1 / rateLimit )
116
- }
106
+ limit , period := limitPeriod (rateLimit )
117
107
now := time .Now ()
118
- slot := now .UnixNano () / dur .Nanoseconds ()
108
+ slot := now .UnixNano () / period .Nanoseconds ()
119
109
120
- if l .Fallback != nil {
121
- allow = l .Fallback .Allow ()
122
- }
123
-
124
- name = allowRateName (name , dur , slot )
125
- count , err := l .incr (name , dur , 1 )
110
+ name = allowRateName (name , period , slot )
111
+ count , err := l .incr (name , period , 1 )
126
112
if err == nil {
127
113
allow = count <= limit
114
+ } else if l .Fallback != nil {
115
+ allow = l .Fallback .Allow ()
128
116
}
129
117
130
118
if ! allow {
131
- delay = time .Duration (slot + 1 )* dur - time .Duration (now .UnixNano ())
119
+ delay = time .Duration (slot + 1 )* period - time .Duration (now .UnixNano ())
132
120
}
133
121
134
122
return delay , allow
135
123
}
136
124
137
- func (l * Limiter ) incr (name string , dur time.Duration , n int64 ) (int64 , error ) {
125
+ func limitPeriod (rl rate.Limit ) (limit int64 , period time.Duration ) {
126
+ period = time .Second
127
+ if rl < 1 {
128
+ limit = 1
129
+ period *= time .Duration (1 / rl )
130
+ } else {
131
+ limit = int64 (rl )
132
+ }
133
+ return limit , period
134
+ }
135
+
136
+ func (l * Limiter ) incr (name string , period time.Duration , n int64 ) (int64 , error ) {
138
137
var incr * redis.IntCmd
139
138
_ , err := l .redis .Pipelined (func (pipe redis.Pipeliner ) error {
140
139
incr = pipe .IncrBy (name , n )
141
- pipe .Expire (name , dur )
140
+ pipe .Expire (name , period + 30 * time . Second )
142
141
return nil
143
142
})
144
143
@@ -150,6 +149,6 @@ func allowName(name string, slot int64) string {
150
149
return fmt .Sprintf ("%s:%s-%d" , redisPrefix , name , slot )
151
150
}
152
151
153
- func allowRateName (name string , dur time.Duration , slot int64 ) string {
154
- return fmt .Sprintf ("%s:%s-%d-%d" , redisPrefix , name , dur , slot )
152
+ func allowRateName (name string , period time.Duration , slot int64 ) string {
153
+ return fmt .Sprintf ("%s:%s-%d-%d" , redisPrefix , name , period , slot )
155
154
}
0 commit comments