forked from YonatanDEV1/nitro-sniper
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrateLimiter.go
More file actions
99 lines (79 loc) · 1.67 KB
/
rateLimiter.go
File metadata and controls
99 lines (79 loc) · 1.67 KB
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package main
import (
"github.com/sasha-s/go-csync"
"context"
"time"
)
type RateLimiter interface {
Close(ctx context.Context)
Reset()
Wait(ctx context.Context) error
Unlock()
}
func NewRateLimiter(opts ...RateLimiterConfigOpt) RateLimiter {
config := DefaultRateLimiterConfig()
config.Apply(opts)
return &rateLimiterImpl{
config: *config,
}
}
type rateLimiterImpl struct {
mu csync.Mutex
reset time.Time
remaining int
config RateLimiterConfig
}
func (l *rateLimiterImpl) Close(ctx context.Context) {
_ = l.mu.CLock(ctx)
}
func (l *rateLimiterImpl) Reset() {
l.reset = time.Time{}
l.remaining = 0
l.mu = csync.Mutex{}
}
func (l *rateLimiterImpl) Wait(ctx context.Context) error {
if err := l.mu.CLock(ctx); err != nil {
return err
}
now := time.Now()
var until time.Time
if l.remaining == 0 && l.reset.After(now) {
until = l.reset
}
if until.After(now) {
select {
case <-ctx.Done():
l.Unlock()
return ctx.Err()
case <-time.After(until.Sub(now)):
}
}
return nil
}
func (l *rateLimiterImpl) Unlock() {
now := time.Now()
if l.reset.Before(now) {
l.reset = now.Add(time.Minute)
l.remaining = l.config.CommandsPerMinute
}
l.mu.Unlock()
}
func DefaultRateLimiterConfig() *RateLimiterConfig {
return &RateLimiterConfig{
CommandsPerMinute: 120,
}
}
type RateLimiterConfig struct {
CommandsPerMinute int
}
type RateLimiterConfigOpt func(config *RateLimiterConfig)
func (c *RateLimiterConfig) Apply(opts []RateLimiterConfigOpt) {
for _, opt := range opts {
opt(c)
}
}
func WithCommandsPerMinute(commandsPerMinute int) RateLimiterConfigOpt {
return func(config *RateLimiterConfig) {
config.CommandsPerMinute = commandsPerMinute
}
}