-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgoralim.go
74 lines (58 loc) · 1.61 KB
/
goralim.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
66
67
68
69
70
package goralim
import(
"time"
"sync"
redis "github.com/go-redis/redis"
)
// `Key` is the identifier for clint calls. This could be UserID/AccountID or Client IP
// `Capacity` is the max number of requests a client can make per second
// `RefillRate` is the rate bucket should be filled at to take new requests
// `Tokens` is the current number of tokens available in bucket
type TokenBucket struct {
Key string
RedisClient *redis.Client
Capacity int
RefillRate int
Tokens int
LastRefilledAt time.Time
mutex sync.Mutex
}
func testFunc(){
}
func NewTokenBucket(key string, redisClient *redis.Client, capacity int, refillRate int) *TokenBucket {
return &TokenBucket {
Key: key,
RedisClient: redisClient,
Capacity: capacity,
RefillRate: refillRate,
Tokens: capacity,
LastRefilledAt: time.Now(),
}
}
func (tb *TokenBucket) refillTokens() {
// Current time in milliseconds
now := time.Now().UnixNano() / 1e6
lastRefill, err := tb.RedisClient.Get(tb.Key + ":lastRefill").Int64()
if err != nil {
lastRefill = now
tb.RedisClient.Set(tb.Key + ":lastRefill", now, 0)
}
elapsedTIme := now - lastRefill
tokensToAdd := int(elapsedTIme) * tb.RefillRate / 1000
currentTokens, _ := tb.RedisClient.Get(tb.Key).Int()
newTokens := currentTokens + tokensToAdd
if newTokens > tb.Capacity {
newTokens = tb.Capacity
}
tb.RedisClient.Set(tb.Key, newTokens, 0)
tb.RedisClient.Set(tb.Key + ":lastRefill", now, 0)
}
func (tb *TokenBucket) isAllowed() bool {
tb.refillTokens()
currentTokens, _ := tb.RedisClient.Get(tb.Key).Int()
if currentTokens > 0 {
tb.RedisClient.Decr(tb.Key)
return true
}
return false
}