github.com/weaviate/weaviate@v1.24.6/usecases/ratelimiter/limiter.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package ratelimiter 13 14 import "sync/atomic" 15 16 // Limiter is a thread-safe counter that can be used for rate-limiting requests 17 type Limiter struct { 18 max int64 19 current int64 20 } 21 22 // New creates a [Limiter] with the specified maximum concurrent requests 23 func New(maxRequests int) *Limiter { 24 return &Limiter{ 25 max: int64(maxRequests), 26 } 27 } 28 29 // If there is still room, TryInc, increases the counter and returns true. If 30 // there are too many concurrent requests it does not increase the counter and 31 // returns false 32 func (l *Limiter) TryInc() bool { 33 if l.max <= 0 { 34 return true 35 } 36 37 new := atomic.AddInt64(&l.current, 1) 38 39 if new <= l.max { 40 return true 41 } 42 43 // undo unsuccessful increment 44 atomic.AddInt64(&l.current, -1) 45 return false 46 } 47 48 func (l *Limiter) Dec() { 49 if l.max <= 0 { 50 return 51 } 52 53 new := atomic.AddInt64(&l.current, -1) 54 if new < 0 { 55 // Should not happen unless some client called Dec multiple times. 56 // Try to reset current to 0. It's ok if swap doesn't happen, since 57 // someone else must've succeeded at fixing current value. 58 atomic.CompareAndSwapInt64(&l.current, new, 0) 59 } 60 }