forked from influxdata/influxdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
limiter.go
61 lines (49 loc) · 1.27 KB
/
limiter.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
package hh
import "time"
type limiter struct {
count int64
limit int64
start time.Time
delay float64
}
// NewRateLimiter returns a new limiter configured to restrict a process to the limit per second.
// limit is the maximum amount that can be used per second. The limit should be > 0. A limit
// <= 0, will not limit the processes.
func NewRateLimiter(limit int64) *limiter {
return &limiter{
start: time.Now(),
limit: limit,
delay: 0.5,
}
}
// Update updates the amount used
func (t *limiter) Update(count int) {
t.count += int64(count)
}
// Delay returns the amount of time, up to 1 second, that caller should wait
// to maintain the configured rate
func (t *limiter) Delay() time.Duration {
if t.limit > 0 {
delta := time.Now().Sub(t.start).Seconds()
rate := int64(float64(t.count) / delta)
// Determine how far off from the max rate we are
delayAdj := float64((t.limit - rate)) / float64(t.limit)
// Don't adjust by more than 1 second at a time
delayAdj = t.clamp(delayAdj, -1, 1)
t.delay -= delayAdj
if t.delay < 0 {
t.delay = 0
}
return time.Duration(t.delay) * time.Second
}
return time.Duration(0)
}
func (t *limiter) clamp(value, min, max float64) float64 {
if value < min {
return min
}
if value > max {
return max
}
return value
}