diff --git a/api/rate/rate.go b/api/rate/rate.go index f791460..0a57634 100644 --- a/api/rate/rate.go +++ b/api/rate/rate.go @@ -38,7 +38,7 @@ type CustomRateLimit struct { } type bucket struct { - lock moreatomic.BusyMutex + lock moreatomic.CtxMutex custom *CustomRateLimit remaining uint64 @@ -48,6 +48,13 @@ type bucket struct { lastReset time.Time // only for custom } +func newBucket() *bucket { + return &bucket{ + lock: *moreatomic.NewCtxMutex(), + remaining: 1, + } +} + func NewLimiter(prefix string) *Limiter { return &Limiter{ Prefix: prefix, @@ -66,9 +73,7 @@ func (l *Limiter) getBucket(path string, store bool) *bucket { } if !ok { - bc := &bucket{ - remaining: 1, - } + bc := newBucket() for _, limit := range l.CustomLimits { if strings.Contains(path, limit.Contains) { @@ -131,11 +136,7 @@ func (l *Limiter) Release(path string, headers http.Header) error { return nil } - defer func() { - // Try and lock the bucket, to prevent unlocking an unlocked lock: - b.lock.TryLock() - b.lock.Unlock() - }() + defer b.lock.Unlock() // Check custom limiter if b.custom != nil { diff --git a/go.mod b/go.mod index 3300271..131de09 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,5 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/pkg/errors v0.9.1 golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 - golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 ) diff --git a/go.sum b/go.sum index d72e377..4e87908 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,6 @@ golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzht golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/utils/moreatomic/mutex.go b/utils/moreatomic/mutex.go index 42402a1..3264ac9 100644 --- a/utils/moreatomic/mutex.go +++ b/utils/moreatomic/mutex.go @@ -2,36 +2,51 @@ package moreatomic import ( "context" - - "golang.org/x/sync/semaphore" ) -type BusyMutex struct { - sema semaphore.Weighted +type CtxMutex struct { + mut chan struct{} } -func NewBusyMutex() *BusyMutex { - return &BusyMutex{ - sema: *semaphore.NewWeighted(1), +func NewCtxMutex() *CtxMutex { + return &CtxMutex{ + mut: make(chan struct{}, 1), } } -func (m *BusyMutex) TryLock() bool { - return m.sema.TryAcquire(1) -} +// func (m *CtxMutex) TryLock() bool { +// select { +// case m.mut <- struct{}{}: +// return true +// default: +// return false +// } +// } -func (m *BusyMutex) IsBusy() bool { - if !m.sema.TryAcquire(1) { - return false +// func (m *CtxMutex) IsBusy() bool { +// select { +// case m.mut <- struct{}{}: +// <-m.mut +// return false +// default: +// return true +// } +// } + +func (m *CtxMutex) Lock(ctx context.Context) error { + select { + case m.mut <- struct{}{}: + return nil + case <-ctx.Done(): + return ctx.Err() } - m.sema.Release(1) - return true } -func (m *BusyMutex) Lock(ctx context.Context) error { - return m.sema.Acquire(ctx, 1) -} - -func (m *BusyMutex) Unlock() { - m.sema.Release(1) +func (m *CtxMutex) Unlock() { + select { + case <-m.mut: + // return + default: + panic("Unlock of already unlocked mutex.") + } }