60 lines
1022 B
Go
60 lines
1022 B
Go
package goutil
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Attenuator struct {
|
|
sync.Mutex
|
|
memory *Memory
|
|
}
|
|
|
|
func NewAttenuator() *Attenuator {
|
|
return &Attenuator{
|
|
memory: NewMemory(),
|
|
}
|
|
}
|
|
|
|
func (a *Attenuator) Do(key string, fun func()) bool {
|
|
a.Lock()
|
|
defer a.Unlock()
|
|
|
|
val := a.memory.Get(key)
|
|
if val == nil {
|
|
fun()
|
|
a.memory.Set(key, fmt.Sprintf("%d,1", time.Now().Unix()), time.Hour*time.Duration(24*365*100))
|
|
return true
|
|
}
|
|
|
|
fields := strings.Split(val.(string), ",")
|
|
|
|
timestamp, _ := strconv.ParseInt(fields[0], 10, 64)
|
|
count, _ := strconv.ParseInt(fields[0], 10, 64)
|
|
|
|
count += 1
|
|
nowTime := time.Now().Unix()
|
|
if nowTime-timestamp <= int64(math.Pow(2, float64(count)))*60 {
|
|
return false
|
|
}
|
|
|
|
fun()
|
|
a.memory.Set(key, fmt.Sprintf("%d,%d", nowTime, count), time.Hour*time.Duration(24*365*100))
|
|
return true
|
|
}
|
|
|
|
func (a *Attenuator) Clear(key string) bool {
|
|
a.Lock()
|
|
defer a.Unlock()
|
|
|
|
if a.memory.IsExist(key) {
|
|
a.memory.Delete(key)
|
|
return true
|
|
}
|
|
return false
|
|
}
|