diff options
author | Paul Okstad <pokstad@gitlab.com> | 2020-04-21 18:47:22 +0300 |
---|---|---|
committer | Paul Okstad <pokstad@gitlab.com> | 2020-04-21 18:47:22 +0300 |
commit | 7ba642fffaf4e2460cf46030ca5296ce32d28c3a (patch) | |
tree | 2c7249635e5a9448bde83d341afc3214f28307e6 | |
parent | 94f891978020c91ce4aa09838eb99b939bca8c9f (diff) | |
parent | 47185f1039cba0c808bc5566325aa2799998a4cf (diff) |
Merge branch 'jv-limithandler-channel' into 'master'
Limithandler: get rid of weighted semaphore
See merge request gitlab-org/gitaly!2079
-rw-r--r-- | NOTICE | 2 | ||||
-rw-r--r-- | internal/middleware/limithandler/concurrency_limiter.go | 38 |
2 files changed, 20 insertions, 20 deletions
@@ -2318,7 +2318,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LICENSE - golang.org/x/sync +LICENSE - golang.org/x/sync/errgroup Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/internal/middleware/limithandler/concurrency_limiter.go b/internal/middleware/limithandler/concurrency_limiter.go index 9c437ed9f..ab3a1cf3e 100644 --- a/internal/middleware/limithandler/concurrency_limiter.go +++ b/internal/middleware/limithandler/concurrency_limiter.go @@ -5,8 +5,6 @@ import ( "fmt" "sync" "time" - - "golang.org/x/sync/semaphore" ) // LimitedFunc represents a function that will be limited @@ -29,30 +27,32 @@ type ConcurrencyLimiter struct { } type semaphoreReference struct { - // A weighted semaphore is like a mutex, but with a number of 'slots'. - // When locking the locker requests 1 or more slots to be locked. - // In this package, the number of slots is the number of concurrent requests the rate limiter lets through. - // https://godoc.org/golang.org/x/sync/semaphore - *semaphore.Weighted - count int + tokens chan struct{} + count int +} + +func (sem *semaphoreReference) acquire(ctx context.Context) error { + select { + case sem.tokens <- struct{}{}: + return nil + case <-ctx.Done(): + return ctx.Err() + } } +func (sem *semaphoreReference) release() { <-sem.tokens } + // Lazy create a semaphore for the given key func (c *ConcurrencyLimiter) getSemaphore(lockKey string) *semaphoreReference { c.mux.Lock() defer c.mux.Unlock() - if ref := c.semaphores[lockKey]; ref != nil { - ref.count++ - return ref + if c.semaphores[lockKey] == nil { + c.semaphores[lockKey] = &semaphoreReference{tokens: make(chan struct{}, c.max)} } - ref := &semaphoreReference{ - Weighted: semaphore.NewWeighted(c.max), - count: 1, // The caller gets this reference so the initial value is 1 - } - c.semaphores[lockKey] = ref - return ref + c.semaphores[lockKey].count++ + return c.semaphores[lockKey] } func (c *ConcurrencyLimiter) putSemaphore(lockKey string) { @@ -93,12 +93,12 @@ func (c *ConcurrencyLimiter) Limit(ctx context.Context, lockKey string, f Limite sem := c.getSemaphore(lockKey) defer c.putSemaphore(lockKey) - err := sem.Acquire(ctx, 1) + err := sem.acquire(ctx) c.monitor.Dequeued(ctx) if err != nil { return nil, err } - defer sem.Release(1) + defer sem.release() c.monitor.Enter(ctx, time.Since(start)) defer c.monitor.Exit(ctx) |