k8s.io/client-go@v0.31.1/util/workqueue/default_rate_limiters.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package workqueue 18 19 import ( 20 "math" 21 "sync" 22 "time" 23 24 "golang.org/x/time/rate" 25 ) 26 27 // Deprecated: RateLimiter is deprecated, use TypedRateLimiter instead. 28 type RateLimiter TypedRateLimiter[any] 29 30 type TypedRateLimiter[T comparable] interface { 31 // When gets an item and gets to decide how long that item should wait 32 When(item T) time.Duration 33 // Forget indicates that an item is finished being retried. Doesn't matter whether it's for failing 34 // or for success, we'll stop tracking it 35 Forget(item T) 36 // NumRequeues returns back how many failures the item has had 37 NumRequeues(item T) int 38 } 39 40 // DefaultControllerRateLimiter is a no-arg constructor for a default rate limiter for a workqueue. It has 41 // both overall and per-item rate limiting. The overall is a token bucket and the per-item is exponential 42 // 43 // Deprecated: Use DefaultTypedControllerRateLimiter instead. 44 func DefaultControllerRateLimiter() RateLimiter { 45 return DefaultTypedControllerRateLimiter[any]() 46 } 47 48 // DefaultTypedControllerRateLimiter is a no-arg constructor for a default rate limiter for a workqueue. It has 49 // both overall and per-item rate limiting. The overall is a token bucket and the per-item is exponential 50 func DefaultTypedControllerRateLimiter[T comparable]() TypedRateLimiter[T] { 51 return NewTypedMaxOfRateLimiter( 52 NewTypedItemExponentialFailureRateLimiter[T](5*time.Millisecond, 1000*time.Second), 53 // 10 qps, 100 bucket size. This is only for retry speed and its only the overall factor (not per item) 54 &TypedBucketRateLimiter[T]{Limiter: rate.NewLimiter(rate.Limit(10), 100)}, 55 ) 56 } 57 58 // Deprecated: BucketRateLimiter is deprecated, use TypedBucketRateLimiter instead. 59 type BucketRateLimiter = TypedBucketRateLimiter[any] 60 61 // TypedBucketRateLimiter adapts a standard bucket to the workqueue ratelimiter API 62 type TypedBucketRateLimiter[T comparable] struct { 63 *rate.Limiter 64 } 65 66 var _ RateLimiter = &BucketRateLimiter{} 67 68 func (r *TypedBucketRateLimiter[T]) When(item T) time.Duration { 69 return r.Limiter.Reserve().Delay() 70 } 71 72 func (r *TypedBucketRateLimiter[T]) NumRequeues(item T) int { 73 return 0 74 } 75 76 func (r *TypedBucketRateLimiter[T]) Forget(item T) { 77 } 78 79 // Deprecated: ItemExponentialFailureRateLimiter is deprecated, use TypedItemExponentialFailureRateLimiter instead. 80 type ItemExponentialFailureRateLimiter = TypedItemExponentialFailureRateLimiter[any] 81 82 // TypedItemExponentialFailureRateLimiter does a simple baseDelay*2^<num-failures> limit 83 // dealing with max failures and expiration are up to the caller 84 type TypedItemExponentialFailureRateLimiter[T comparable] struct { 85 failuresLock sync.Mutex 86 failures map[T]int 87 88 baseDelay time.Duration 89 maxDelay time.Duration 90 } 91 92 var _ RateLimiter = &ItemExponentialFailureRateLimiter{} 93 94 // Deprecated: NewItemExponentialFailureRateLimiter is deprecated, use NewTypedItemExponentialFailureRateLimiter instead. 95 func NewItemExponentialFailureRateLimiter(baseDelay time.Duration, maxDelay time.Duration) RateLimiter { 96 return NewTypedItemExponentialFailureRateLimiter[any](baseDelay, maxDelay) 97 } 98 99 func NewTypedItemExponentialFailureRateLimiter[T comparable](baseDelay time.Duration, maxDelay time.Duration) TypedRateLimiter[T] { 100 return &TypedItemExponentialFailureRateLimiter[T]{ 101 failures: map[T]int{}, 102 baseDelay: baseDelay, 103 maxDelay: maxDelay, 104 } 105 } 106 107 // Deprecated: DefaultItemBasedRateLimiter is deprecated, use DefaultTypedItemBasedRateLimiter instead. 108 func DefaultItemBasedRateLimiter() RateLimiter { 109 return DefaultTypedItemBasedRateLimiter[any]() 110 } 111 112 func DefaultTypedItemBasedRateLimiter[T comparable]() TypedRateLimiter[T] { 113 return NewTypedItemExponentialFailureRateLimiter[T](time.Millisecond, 1000*time.Second) 114 } 115 116 func (r *TypedItemExponentialFailureRateLimiter[T]) When(item T) time.Duration { 117 r.failuresLock.Lock() 118 defer r.failuresLock.Unlock() 119 120 exp := r.failures[item] 121 r.failures[item] = r.failures[item] + 1 122 123 // The backoff is capped such that 'calculated' value never overflows. 124 backoff := float64(r.baseDelay.Nanoseconds()) * math.Pow(2, float64(exp)) 125 if backoff > math.MaxInt64 { 126 return r.maxDelay 127 } 128 129 calculated := time.Duration(backoff) 130 if calculated > r.maxDelay { 131 return r.maxDelay 132 } 133 134 return calculated 135 } 136 137 func (r *TypedItemExponentialFailureRateLimiter[T]) NumRequeues(item T) int { 138 r.failuresLock.Lock() 139 defer r.failuresLock.Unlock() 140 141 return r.failures[item] 142 } 143 144 func (r *TypedItemExponentialFailureRateLimiter[T]) Forget(item T) { 145 r.failuresLock.Lock() 146 defer r.failuresLock.Unlock() 147 148 delete(r.failures, item) 149 } 150 151 // ItemFastSlowRateLimiter does a quick retry for a certain number of attempts, then a slow retry after that 152 // Deprecated: Use TypedItemFastSlowRateLimiter instead. 153 type ItemFastSlowRateLimiter = TypedItemFastSlowRateLimiter[any] 154 155 // TypedItemFastSlowRateLimiter does a quick retry for a certain number of attempts, then a slow retry after that 156 type TypedItemFastSlowRateLimiter[T comparable] struct { 157 failuresLock sync.Mutex 158 failures map[T]int 159 160 maxFastAttempts int 161 fastDelay time.Duration 162 slowDelay time.Duration 163 } 164 165 var _ RateLimiter = &ItemFastSlowRateLimiter{} 166 167 // Deprecated: NewItemFastSlowRateLimiter is deprecated, use NewTypedItemFastSlowRateLimiter instead. 168 func NewItemFastSlowRateLimiter(fastDelay, slowDelay time.Duration, maxFastAttempts int) RateLimiter { 169 return NewTypedItemFastSlowRateLimiter[any](fastDelay, slowDelay, maxFastAttempts) 170 } 171 172 func NewTypedItemFastSlowRateLimiter[T comparable](fastDelay, slowDelay time.Duration, maxFastAttempts int) TypedRateLimiter[T] { 173 return &TypedItemFastSlowRateLimiter[T]{ 174 failures: map[T]int{}, 175 fastDelay: fastDelay, 176 slowDelay: slowDelay, 177 maxFastAttempts: maxFastAttempts, 178 } 179 } 180 181 func (r *TypedItemFastSlowRateLimiter[T]) When(item T) time.Duration { 182 r.failuresLock.Lock() 183 defer r.failuresLock.Unlock() 184 185 r.failures[item] = r.failures[item] + 1 186 187 if r.failures[item] <= r.maxFastAttempts { 188 return r.fastDelay 189 } 190 191 return r.slowDelay 192 } 193 194 func (r *TypedItemFastSlowRateLimiter[T]) NumRequeues(item T) int { 195 r.failuresLock.Lock() 196 defer r.failuresLock.Unlock() 197 198 return r.failures[item] 199 } 200 201 func (r *TypedItemFastSlowRateLimiter[T]) Forget(item T) { 202 r.failuresLock.Lock() 203 defer r.failuresLock.Unlock() 204 205 delete(r.failures, item) 206 } 207 208 // MaxOfRateLimiter calls every RateLimiter and returns the worst case response 209 // When used with a token bucket limiter, the burst could be apparently exceeded in cases where particular items 210 // were separately delayed a longer time. 211 // 212 // Deprecated: Use TypedMaxOfRateLimiter instead. 213 type MaxOfRateLimiter = TypedMaxOfRateLimiter[any] 214 215 // TypedMaxOfRateLimiter calls every RateLimiter and returns the worst case response 216 // When used with a token bucket limiter, the burst could be apparently exceeded in cases where particular items 217 // were separately delayed a longer time. 218 type TypedMaxOfRateLimiter[T comparable] struct { 219 limiters []TypedRateLimiter[T] 220 } 221 222 func (r *TypedMaxOfRateLimiter[T]) When(item T) time.Duration { 223 ret := time.Duration(0) 224 for _, limiter := range r.limiters { 225 curr := limiter.When(item) 226 if curr > ret { 227 ret = curr 228 } 229 } 230 231 return ret 232 } 233 234 // Deprecated: NewMaxOfRateLimiter is deprecated, use NewTypedMaxOfRateLimiter instead. 235 func NewMaxOfRateLimiter(limiters ...TypedRateLimiter[any]) RateLimiter { 236 return NewTypedMaxOfRateLimiter(limiters...) 237 } 238 239 func NewTypedMaxOfRateLimiter[T comparable](limiters ...TypedRateLimiter[T]) TypedRateLimiter[T] { 240 return &TypedMaxOfRateLimiter[T]{limiters: limiters} 241 } 242 243 func (r *TypedMaxOfRateLimiter[T]) NumRequeues(item T) int { 244 ret := 0 245 for _, limiter := range r.limiters { 246 curr := limiter.NumRequeues(item) 247 if curr > ret { 248 ret = curr 249 } 250 } 251 252 return ret 253 } 254 255 func (r *TypedMaxOfRateLimiter[T]) Forget(item T) { 256 for _, limiter := range r.limiters { 257 limiter.Forget(item) 258 } 259 } 260 261 // WithMaxWaitRateLimiter have maxDelay which avoids waiting too long 262 // Deprecated: Use TypedWithMaxWaitRateLimiter instead. 263 type WithMaxWaitRateLimiter = TypedWithMaxWaitRateLimiter[any] 264 265 // TypedWithMaxWaitRateLimiter have maxDelay which avoids waiting too long 266 type TypedWithMaxWaitRateLimiter[T comparable] struct { 267 limiter TypedRateLimiter[T] 268 maxDelay time.Duration 269 } 270 271 // Deprecated: NewWithMaxWaitRateLimiter is deprecated, use NewTypedWithMaxWaitRateLimiter instead. 272 func NewWithMaxWaitRateLimiter(limiter RateLimiter, maxDelay time.Duration) RateLimiter { 273 return NewTypedWithMaxWaitRateLimiter[any](limiter, maxDelay) 274 } 275 276 func NewTypedWithMaxWaitRateLimiter[T comparable](limiter TypedRateLimiter[T], maxDelay time.Duration) TypedRateLimiter[T] { 277 return &TypedWithMaxWaitRateLimiter[T]{limiter: limiter, maxDelay: maxDelay} 278 } 279 280 func (w TypedWithMaxWaitRateLimiter[T]) When(item T) time.Duration { 281 delay := w.limiter.When(item) 282 if delay > w.maxDelay { 283 return w.maxDelay 284 } 285 286 return delay 287 } 288 289 func (w TypedWithMaxWaitRateLimiter[T]) Forget(item T) { 290 w.limiter.Forget(item) 291 } 292 293 func (w TypedWithMaxWaitRateLimiter[T]) NumRequeues(item T) int { 294 return w.limiter.NumRequeues(item) 295 }