File: throttle.go

package info (click to toggle)
golang-github-araddon-gou 0.0~git20180509.7db4be5-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 160 kB
  • sloc: makefile: 2
file content (75 lines) | stat: -rw-r--r-- 1,864 bytes parent folder | download | duplicates (2)
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
66
67
68
69
70
71
72
73
74
75
package gou

import (
	"time"
)

type Throttler struct {

	// Limit to this events/per
	maxPer float64
	per    float64
	count  int32

	// Last Event
	last time.Time

	// How many events are allowed left to happen?
	// Starts at limit, decrements down
	allowance float64
}

// new Throttler that will tell you to limit or not based
// on given @max events @per duration
func NewThrottler(max int, per time.Duration) *Throttler {
	return &Throttler{
		maxPer:    float64(max),
		allowance: float64(max),
		count:     int32(0),
		last:      time.Now(),
		per:       per.Seconds(),
	}
}

// Should we limit this because we are above rate?
// Returns a bool of whether to throttle the message, and a count
// of previous log messages throttled since last log message.
func (r *Throttler) ThrottleAdd(ct int32) (bool, int32) {

	if r.maxPer == 0 {
		return false, 0
	}

	// http://stackoverflow.com/questions/667508/whats-a-good-rate-limiting-algorithm
	now := time.Now()
	elapsed := float64(now.Sub(r.last).Nanoseconds()) / 1e9 // seconds
	r.last = now
	r.allowance += elapsed * (r.maxPer / r.per)

	//Infof("maxRate: %v  cur: %v elapsed:%-6.6f  incr: %v", r.maxPer, int(r.allowance), elapsed, elapsed*float64(r.maxPer))
	if r.allowance > r.maxPer {
		r.allowance = r.maxPer
	}

	if r.allowance < 1.0 {
		r.count += ct        // increment throttled log count
		return true, r.count // do throttle/limit
	}

	tmpCount := r.count
	r.count = 0 // reset count

	r.allowance -= 1.0
	return false, tmpCount // dont throttle, return previous throttle count
}

// Should we limit this because we are above rate?
// Returns a bool of whether to throttle the message, and a count
// of previous log messages throttled since last log message.
func (r *Throttler) Throttle() (bool, int32) {
	return r.ThrottleAdd(1)
}

func (r *Throttler) ThrottleCount() int32 {
	return r.count
}