-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlimit.go
65 lines (54 loc) · 1.12 KB
/
limit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package rate
import "time"
// Limit is a simple rate-limiter.
// It counts ticks and provides the most recent value of ticks/freq.
type Limit struct {
count int
freq time.Duration
chTick chan struct{}
chClose chan struct{}
}
// NewLimit returns an initialized Limit{} that limits the rate to 1/f ticks.
func NewLimit(f time.Duration) *Limit {
if f.Nanoseconds() <= int64(0) {
f = time.Duration(1 * time.Nanosecond)
}
limit := &Limit{
freq: f,
chTick: make(chan struct{}),
chClose: make(chan struct{}),
}
go func() {
defer func() {
close(limit.chTick)
close(limit.chClose)
}()
tick := time.Tick(f)
for {
select {
case <-limit.chClose:
return
case <-tick:
limit.chTick <- struct{}{}
}
}
}()
return limit
}
// Wait blocks until the next free token becomes available.
func (l Limit) Wait() {
<-l.chTick
}
// Try returns nil if a free token was available and an errTooFast, otherwise.
func (l Limit) Try() error {
select {
case <-l.chTick:
return nil
default:
return errTooFast
}
}
// Close frees the underlying resources.
func (l Limit) Close() {
l.chClose <- struct{}{}
}