-
Notifications
You must be signed in to change notification settings - Fork 159
/
failure.go
105 lines (91 loc) · 2.39 KB
/
failure.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
package xt
import (
cmap "github.com/orcaman/concurrent-map/v2"
"time"
)
type failureCosts struct {
costMap cmap.ConcurrentMap[string, uint16]
maxFailureCost uint32
failureCost uint16
successCredit uint16
}
func NewFailureCosts(maxFailureCost uint16, failureCost uint8, successCredit uint8) FailureCosts {
result := &failureCosts{
costMap: cmap.New[uint16](),
maxFailureCost: uint32(maxFailureCost),
failureCost: uint16(failureCost),
successCredit: uint16(successCredit),
}
return result
}
func (self *failureCosts) CreditOverTime(credit uint8, period time.Duration) *time.Ticker {
ticker := time.NewTicker(period)
go func() {
for range ticker.C {
for val := range self.costMap.IterBuffered() {
actualCredit := self.successWithCredit(val.Key, uint16(credit))
GlobalCosts().UpdateDynamicCost(val.Key, func(u uint16) uint16 {
if u < actualCredit {
return 0
}
return u - actualCredit
})
}
}
}()
return ticker
}
func (self *failureCosts) Clear(terminatorId string) {
self.costMap.Remove(terminatorId)
}
func (self *failureCosts) Failure(terminatorId string) uint16 {
var change uint16
self.costMap.Upsert(terminatorId, 0, func(exist bool, currentCost uint16, newValue uint16) uint16 {
if !exist {
change = self.failureCost
return self.failureCost
}
nextCost := uint32(currentCost) + uint32(self.failureCost)
if nextCost > self.maxFailureCost {
change = uint16(self.maxFailureCost - uint32(currentCost))
return uint16(self.maxFailureCost)
}
change = self.failureCost
return uint16(nextCost)
})
return change
}
func (self *failureCosts) Success(terminatorId string) uint16 {
return self.successWithCredit(terminatorId, self.successCredit)
}
func (self *failureCosts) successWithCredit(terminatorId string, credit uint16) uint16 {
val, found := self.costMap.Get(terminatorId)
if !found {
return 0
}
if val == 0 {
removed := self.costMap.RemoveCb(terminatorId, func(key string, currentVal uint16, exists bool) bool {
if !exists {
return true
}
return currentVal == 0
})
if removed {
return 0
}
}
var change uint16
self.costMap.Upsert(terminatorId, 0, func(exist bool, currentCost uint16, newValue uint16) uint16 {
if !exist {
change = 0
return 0
}
if currentCost < credit {
change = currentCost
return 0
}
change = credit
return currentCost - credit
})
return change
}