mirror of
https://github.com/status-im/status-go.git
synced 2025-01-12 23:55:03 +00:00
38308d48f2
* feat_: log error and stacktrace when panic in goroutine * test_: add test TestSafeGo * chore_: rename logAndCall to call * chore_: rename SafeGo to Go * chore_: make lint-fix * chore_: use t.Cleanup * chore_: Revert "chore_: use t.Cleanup" This reverts commit 4eb420d179cc0e208e84c13cb941e6b3d1ed9819. * chore_: Revert "chore_: make lint-fix" This reverts commit fcc995f157e671a4229b47419c3a0e4004b5fdab. * chore_: Revert "chore_: rename SafeGo to Go" This reverts commit a6d73d6df583f313032d79aac62f66328039cb55. * chore_: Revert "chore_: rename logAndCall to call" This reverts commit 8fbe993bedb9fbba67349a44f151e2dd5e3bc4cc. * chore_: Revert "test_: add test TestSafeGo" This reverts commit a1fa91839f3960398980c6bf456e6462ec944819. * chore_: Revert "feat_: log error and stacktrace when panic in goroutine" This reverts commit f612dd828fa2ce410d0e806fe773ecbe3e86a68a. * feat_: log error and stacktrace when panic in goroutine * chore_: make lint-fix * chore_: rename logAndCall to call * chore_: renaming LogOnPanic * chore_: update rest goroutine function calls * chore_: make lint-fix
92 lines
1.4 KiB
Go
92 lines
1.4 KiB
Go
package mailserver
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/status-im/status-go/common"
|
|
)
|
|
|
|
type rateLimiter struct {
|
|
sync.RWMutex
|
|
|
|
lifespan time.Duration // duration of the limit
|
|
db map[string]time.Time
|
|
|
|
period time.Duration
|
|
cancel chan struct{}
|
|
}
|
|
|
|
func newRateLimiter(duration time.Duration) *rateLimiter {
|
|
return &rateLimiter{
|
|
lifespan: duration,
|
|
db: make(map[string]time.Time),
|
|
period: time.Second,
|
|
}
|
|
}
|
|
|
|
func (l *rateLimiter) Start() {
|
|
cancel := make(chan struct{})
|
|
|
|
l.Lock()
|
|
l.cancel = cancel
|
|
l.Unlock()
|
|
|
|
go l.cleanUp(l.period, cancel)
|
|
}
|
|
|
|
func (l *rateLimiter) Stop() {
|
|
l.Lock()
|
|
defer l.Unlock()
|
|
|
|
if l.cancel == nil {
|
|
return
|
|
}
|
|
close(l.cancel)
|
|
l.cancel = nil
|
|
}
|
|
|
|
func (l *rateLimiter) Add(id string) {
|
|
l.Lock()
|
|
l.db[id] = time.Now()
|
|
l.Unlock()
|
|
}
|
|
|
|
func (l *rateLimiter) IsAllowed(id string) bool {
|
|
l.RLock()
|
|
defer l.RUnlock()
|
|
|
|
if lastRequestTime, ok := l.db[id]; ok {
|
|
return lastRequestTime.Add(l.lifespan).Before(time.Now())
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (l *rateLimiter) cleanUp(period time.Duration, cancel <-chan struct{}) {
|
|
defer common.LogOnPanic()
|
|
t := time.NewTicker(period)
|
|
defer t.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-t.C:
|
|
l.deleteExpired()
|
|
case <-cancel:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *rateLimiter) deleteExpired() {
|
|
l.Lock()
|
|
defer l.Unlock()
|
|
|
|
now := time.Now()
|
|
for id, lastRequestTime := range l.db {
|
|
if lastRequestTime.Add(l.lifespan).Before(now) {
|
|
delete(l.db, id)
|
|
}
|
|
}
|
|
}
|