2024-08-14 23:28:07 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type SlidingWindowCounter struct {
|
|
|
|
mu sync.Mutex
|
|
|
|
events []time.Time
|
|
|
|
windowSize time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSlidingWindowCounter(windowSize time.Duration) *SlidingWindowCounter {
|
2024-08-15 00:58:36 +02:00
|
|
|
swc := &SlidingWindowCounter{
|
2024-08-14 23:28:07 +02:00
|
|
|
events: make([]time.Time, 0),
|
|
|
|
windowSize: windowSize,
|
|
|
|
}
|
2024-08-15 00:58:36 +02:00
|
|
|
|
|
|
|
// Start a goroutine to periodically remove old events
|
|
|
|
go func() {
|
|
|
|
ticker := time.NewTicker(time.Second)
|
|
|
|
defer ticker.Stop()
|
|
|
|
|
|
|
|
for range ticker.C {
|
|
|
|
swc.mu.Lock()
|
|
|
|
swc.removeOldEvents(time.Now())
|
|
|
|
swc.mu.Unlock()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return swc
|
2024-08-14 23:28:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (swc *SlidingWindowCounter) Increment() {
|
|
|
|
swc.mu.Lock()
|
|
|
|
defer swc.mu.Unlock()
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
swc.events = append(swc.events, now)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (swc *SlidingWindowCounter) Count() int {
|
|
|
|
swc.mu.Lock()
|
|
|
|
defer swc.mu.Unlock()
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
swc.removeOldEvents(now)
|
|
|
|
return len(swc.events)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (swc *SlidingWindowCounter) removeOldEvents(now time.Time) {
|
|
|
|
cutoff := now.Add(-swc.windowSize)
|
|
|
|
i := 0
|
|
|
|
for ; i < len(swc.events); i++ {
|
|
|
|
if swc.events[i].After(cutoff) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
swc.events = swc.events[i:]
|
|
|
|
}
|