-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
123 lines (96 loc) · 3.42 KB
/
main.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
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package adaptivethrottling
import (
"math"
"math/rand"
"time"
)
type adaptiveThrottlingHistory struct {
requestsHistory []int64
acceptsHistory []int64
}
// Função utilitária para filtrar registros mais antigos do histórico
func filterOldestHistory(historyTimeMinute int, value int64) bool {
date := time.Now().Unix() - int64(historyTimeMinute*60)
return value > date
}
// Cria uma nova instância do adaptiveThrottlingHistory
func createAdaptiveThrottlingHistory(historyTimeMinute int) *adaptiveThrottlingHistory {
return &adaptiveThrottlingHistory{
requestsHistory: []int64{},
acceptsHistory: []int64{},
}
}
// Adiciona uma nova requisição ao histórico
func (h *adaptiveThrottlingHistory) addRequests() {
h.requestsHistory = append(h.requestsHistory, time.Now().Unix())
}
// Adiciona uma nova requisição aceita ao histórico
func (h *adaptiveThrottlingHistory) addAccepts() {
h.acceptsHistory = append(h.acceptsHistory, time.Now().Unix())
}
// filter é uma função auxiliar para filtrar elementos de um slice baseado em um predicado
func filter(slice []int64, predicate func(value int64) bool) []int64 {
result := make([]int64, 0, len(slice))
for _, value := range slice {
if predicate(value) {
result = append(result, value)
}
}
return result
}
// Atualiza o histórico removendo registros mais antigos
func (h *adaptiveThrottlingHistory) refresh(historyTimeMinute int) {
filterFn := func(value int64) bool {
return filterOldestHistory(historyTimeMinute, value)
}
h.requestsHistory = filter(h.requestsHistory, filterFn)
h.acceptsHistory = filter(h.acceptsHistory, filterFn)
}
// Retorna o comprimento do histórico de requisições
func (h *adaptiveThrottlingHistory) getRequestsHistoryLength() int {
return len(h.requestsHistory)
}
// Retorna o comprimento do histórico de requisições aceitas
func (h *adaptiveThrottlingHistory) getAcceptsHistoryLength() int {
return len(h.acceptsHistory)
}
// New é uma função que cria uma instância do adaptive throttling com base nas opções fornecidas.
func New(opts Options) func(func() (interface{}, error)) (interface{}, error) {
opts.Fill()
requestRejectionProbability := 0.0
adaptiveThrottling := createAdaptiveThrottlingHistory(opts.HistoryTimeMinute)
// Função utilitária para verificar a probabilidade de rejeição de uma nova requisição
checkRequestRejectionProbability := func() bool {
return rand.Float64() < requestRejectionProbability
}
// Função utilitária para atualizar a probabilidade de rejeição de requisições
updateRequestRejectionProbability := func() {
adaptiveThrottling.refresh(opts.HistoryTimeMinute)
requests := adaptiveThrottling.getRequestsHistoryLength()
accepts := adaptiveThrottling.getAcceptsHistoryLength()
p0 := math.Max(0, (float64(requests)-opts.K*float64(accepts))/(float64(requests)+1))
p1 := math.Min(p0, opts.UpperLimitToReject)
requestRejectionProbability = p1
}
return func(fn func() (interface{}, error)) (interface{}, error) {
adaptiveThrottling.addRequests()
if checkRequestRejectionProbability() {
updateRequestRejectionProbability()
return nil, ThrottledException{}
}
startTime := time.Now()
result, err := fn()
if err != nil {
updateRequestRejectionProbability()
return nil, err
}
duration := time.Since(startTime)
if duration.Seconds() < 1 {
adaptiveThrottling.addAccepts()
}
updateRequestRejectionProbability()
return result, nil
}
}
func main() {
}