1
0
mirror of https://github.com/coalaura/up.git synced 2025-07-17 21:44:35 +00:00
Files
up/server/rates.go
2025-06-20 22:44:16 +02:00

65 lines
990 B
Go

package main
import (
"sync"
"sync/atomic"
)
type RateLimiter struct {
sync.Map
total atomic.Uint32
}
const MinusOne uint32 = ^uint32(0)
func NewRateLimiter() *RateLimiter {
return &RateLimiter{}
}
func (rl *RateLimiter) Get(key string) *atomic.Uint32 {
val, ok := rl.Map.Load(key)
if ok {
return val.(*atomic.Uint32)
}
actual, _ := rl.Map.LoadOrStore(key, &atomic.Uint32{})
return actual.(*atomic.Uint32)
}
func (rl *RateLimiter) Inc(key string) (uint32, func(), func()) {
if rl.total.Add(1) > MaxGlobalParallel {
rl.total.Add(MinusOne)
return 0, nil, nil
}
val := rl.Get(key)
new := val.Add(1)
var done uint32
pass := func() {
atomic.CompareAndSwapUint32(&done, 0, 1)
}
fail := func() {
if !atomic.CompareAndSwapUint32(&done, 0, 1) {
return
}
rl.total.Add(MinusOne)
val.Add(MinusOne)
}
return new, pass, fail
}
func (rl *RateLimiter) Dec(key string) uint32 {
rl.total.Add(MinusOne)
val := rl.Get(key)
return val.Add(MinusOne)
}