bitbucket.org/Aishee/synsec@v0.0.0-20210414005726-236fc01a153d/pkg/time/rate/rate.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package rate provides a rate limiter. 6 package rate 7 8 import ( 9 "context" 10 "fmt" 11 "math" 12 "sync" 13 "time" 14 ) 15 16 // Limit defines the maximum frequency of some events. 17 // Limit is represented as number of events per second. 18 // A zero Limit allows no events. 19 type Limit float64 20 21 // Inf is the infinite rate limit; it allows all events (even if burst is zero). 22 const Inf = Limit(math.MaxFloat64) 23 24 // Every converts a minimum time interval between events to a Limit. 25 func Every(interval time.Duration) Limit { 26 if interval <= 0 { 27 return Inf 28 } 29 return 1 / Limit(interval.Seconds()) 30 } 31 32 // A Limiter controls how frequently events are allowed to happen. 33 // It implements a "token bucket" of size b, initially full and refilled 34 // at rate r tokens per second. 35 // Informally, in any large enough time interval, the Limiter limits the 36 // rate to r tokens per second, with a maximum burst size of b events. 37 // As a special case, if r == Inf (the infinite rate), b is ignored. 38 // See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets. 39 // 40 // The zero value is a valid Limiter, but it will reject all events. 41 // Use NewLimiter to create non-zero Limiters. 42 // 43 // Limiter has three main methods, Allow, Reserve, and Wait. 44 // Most callers should use Wait. 45 // 46 // Each of the three methods consumes a single token. 47 // They differ in their behavior when no token is available. 48 // If no token is available, Allow returns false. 49 // If no token is available, Reserve returns a reservation for a future token 50 // and the amount of time the caller must wait before using it. 51 // If no token is available, Wait blocks until one can be obtained 52 // or its associated context.Context is canceled. 53 // 54 // The methods AllowN, ReserveN, and WaitN consume n tokens. 55 type Limiter struct { 56 limit Limit 57 burst int 58 59 mu sync.Mutex 60 tokens float64 61 // last is the last time the limiter's tokens field was updated 62 last time.Time 63 // lastEvent is the latest time of a rate-limited event (past or future) 64 lastEvent time.Time 65 } 66 67 type RateLimiter interface { 68 Allow() bool 69 AllowN(time.Time, int) bool 70 GetTokensCount() float64 71 GetTokensCountAt(time.Time) float64 72 Dump() Lstate 73 Load(Lstate) 74 } 75 76 type Lstate struct { 77 Limit Limit 78 Burst int 79 Tokens float64 80 Last time.Time 81 LastEvent time.Time 82 } 83 84 func (lim *Limiter) Dump() Lstate { 85 st := Lstate{} 86 st.Limit = lim.limit 87 st.Burst = lim.burst 88 st.Tokens = lim.tokens 89 st.Last = lim.last 90 st.LastEvent = lim.lastEvent 91 return st 92 } 93 94 func (lim *Limiter) Load(st Lstate) { 95 lim.limit = st.Limit 96 lim.burst = st.Burst 97 lim.tokens = st.Tokens 98 lim.last = st.Last 99 lim.lastEvent = st.LastEvent 100 return 101 } 102 103 // Limit returns the maximum overall event rate. 104 func (lim *Limiter) Limit() Limit { 105 lim.mu.Lock() 106 defer lim.mu.Unlock() 107 return lim.limit 108 } 109 110 // Burst returns the maximum burst size. Burst is the maximum number of tokens 111 // that can be consumed in a single call to Allow, Reserve, or Wait, so higher 112 // Burst values allow more events to happen at once. 113 // A zero Burst allows no events, unless limit == Inf. 114 func (lim *Limiter) Burst() int { 115 return lim.burst 116 } 117 118 // NewLimiter returns a new Limiter that allows events up to rate r and permits 119 // bursts of at most b tokens. 120 func NewLimiter(r Limit, b int) *Limiter { 121 return &Limiter{ 122 limit: r, 123 burst: b, 124 } 125 } 126 127 // Allow is shorthand for AllowN(time.Now(), 1). 128 func (lim *Limiter) Allow() bool { 129 return lim.AllowN(time.Now(), 1) 130 } 131 132 // AllowN reports whether n events may happen at time now. 133 // Use this method if you intend to drop / skip events that exceed the rate limit. 134 // Otherwise use Reserve or Wait. 135 func (lim *Limiter) AllowN(now time.Time, n int) bool { 136 return lim.reserveN(now, n, 0).ok 137 } 138 139 // A Reservation holds information about events that are permitted by a Limiter to happen after a delay. 140 // A Reservation may be canceled, which may enable the Limiter to permit additional events. 141 type Reservation struct { 142 ok bool 143 lim *Limiter 144 tokens int 145 timeToAct time.Time 146 // This is the Limit at reservation time, it can change later. 147 limit Limit 148 } 149 150 // OK returns whether the limiter can provide the requested number of tokens 151 // within the maximum wait time. If OK is false, Delay returns InfDuration, and 152 // Cancel does nothing. 153 func (r *Reservation) OK() bool { 154 return r.ok 155 } 156 157 // Delay is shorthand for DelayFrom(time.Now()). 158 func (r *Reservation) Delay() time.Duration { 159 return r.DelayFrom(time.Now()) 160 } 161 162 // InfDuration is the duration returned by Delay when a Reservation is not OK. 163 const InfDuration = time.Duration(1<<63 - 1) 164 165 // DelayFrom returns the duration for which the reservation holder must wait 166 // before taking the reserved action. Zero duration means act immediately. 167 // InfDuration means the limiter cannot grant the tokens requested in this 168 // Reservation within the maximum wait time. 169 func (r *Reservation) DelayFrom(now time.Time) time.Duration { 170 if !r.ok { 171 return InfDuration 172 } 173 delay := r.timeToAct.Sub(now) 174 if delay < 0 { 175 return 0 176 } 177 return delay 178 } 179 180 // Cancel is shorthand for CancelAt(time.Now()). 181 func (r *Reservation) Cancel() { 182 r.CancelAt(time.Now()) 183 return 184 } 185 186 // CancelAt indicates that the reservation holder will not perform the reserved action 187 // and reverses the effects of this Reservation on the rate limit as much as possible, 188 // considering that other reservations may have already been made. 189 func (r *Reservation) CancelAt(now time.Time) { 190 if !r.ok { 191 return 192 } 193 194 r.lim.mu.Lock() 195 defer r.lim.mu.Unlock() 196 197 if r.lim.limit == Inf || r.tokens == 0 || r.timeToAct.Before(now) { 198 return 199 } 200 201 // calculate tokens to restore 202 // The duration between lim.lastEvent and r.timeToAct tells us how many tokens were reserved 203 // after r was obtained. These tokens should not be restored. 204 restoreTokens := float64(r.tokens) - r.limit.tokensFromDuration(r.lim.lastEvent.Sub(r.timeToAct)) 205 if restoreTokens <= 0 { 206 return 207 } 208 // advance time to now 209 now, _, tokens := r.lim.advance(now) 210 // calculate new number of tokens 211 tokens += restoreTokens 212 if burst := float64(r.lim.burst); tokens > burst { 213 tokens = burst 214 } 215 // update state 216 r.lim.last = now 217 r.lim.tokens = tokens 218 if r.timeToAct == r.lim.lastEvent { 219 prevEvent := r.timeToAct.Add(r.limit.durationFromTokens(float64(-r.tokens))) 220 if !prevEvent.Before(now) { 221 r.lim.lastEvent = prevEvent 222 } 223 } 224 225 return 226 } 227 228 // Reserve is shorthand for ReserveN(time.Now(), 1). 229 func (lim *Limiter) Reserve() *Reservation { 230 return lim.ReserveN(time.Now(), 1) 231 } 232 233 // ReserveN returns a Reservation that indicates how long the caller must wait before n events happen. 234 // The Limiter takes this Reservation into account when allowing future events. 235 // ReserveN returns false if n exceeds the Limiter's burst size. 236 // Usage example: 237 // r := lim.ReserveN(time.Now(), 1) 238 // if !r.OK() { 239 // // Not allowed to act! Did you remember to set lim.burst to be > 0 ? 240 // return 241 // } 242 // time.Sleep(r.Delay()) 243 // Act() 244 // Use this method if you wish to wait and slow down in accordance with the rate limit without dropping events. 245 // If you need to respect a deadline or cancel the delay, use Wait instead. 246 // To drop or skip events exceeding rate limit, use Allow instead. 247 func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation { 248 r := lim.reserveN(now, n, InfDuration) 249 return &r 250 } 251 252 // Wait is shorthand for WaitN(ctx, 1). 253 func (lim *Limiter) Wait(ctx context.Context) (err error) { 254 return lim.WaitN(ctx, 1) 255 } 256 257 // WaitN blocks until lim permits n events to happen. 258 // It returns an error if n exceeds the Limiter's burst size, the Context is 259 // canceled, or the expected wait time exceeds the Context's Deadline. 260 // The burst limit is ignored if the rate limit is Inf. 261 func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { 262 lim.mu.Lock() 263 burst := lim.burst 264 limit := lim.limit 265 lim.mu.Unlock() 266 267 if n > burst && limit != Inf { 268 return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst) 269 } 270 // Check if ctx is already cancelled 271 select { 272 case <-ctx.Done(): 273 return ctx.Err() 274 default: 275 } 276 // Determine wait limit 277 now := time.Now() 278 waitLimit := InfDuration 279 if deadline, ok := ctx.Deadline(); ok { 280 waitLimit = deadline.Sub(now) 281 } 282 // Reserve 283 r := lim.reserveN(now, n, waitLimit) 284 if !r.ok { 285 return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", n) 286 } 287 // Wait if necessary 288 delay := r.DelayFrom(now) 289 if delay == 0 { 290 return nil 291 } 292 t := time.NewTimer(delay) 293 defer t.Stop() 294 select { 295 case <-t.C: 296 // We can proceed. 297 return nil 298 case <-ctx.Done(): 299 // Context was canceled before we could proceed. Cancel the 300 // reservation, which may permit other events to proceed sooner. 301 r.Cancel() 302 return ctx.Err() 303 } 304 } 305 306 // SetLimit is shorthand for SetLimitAt(time.Now(), newLimit). 307 func (lim *Limiter) SetLimit(newLimit Limit) { 308 lim.SetLimitAt(time.Now(), newLimit) 309 } 310 311 // SetLimitAt sets a new Limit for the limiter. The new Limit, and Burst, may be violated 312 // or underutilized by those which reserved (using Reserve or Wait) but did not yet act 313 // before SetLimitAt was called. 314 func (lim *Limiter) SetLimitAt(now time.Time, newLimit Limit) { 315 lim.mu.Lock() 316 defer lim.mu.Unlock() 317 318 now, _, tokens := lim.advance(now) 319 320 lim.last = now 321 lim.tokens = tokens 322 lim.limit = newLimit 323 } 324 325 // SetBurst is shorthand for SetBurstAt(time.Now(), newBurst). 326 func (lim *Limiter) SetBurst(newBurst int) { 327 lim.SetBurstAt(time.Now(), newBurst) 328 } 329 330 // SetBurstAt sets a new burst size for the limiter. 331 func (lim *Limiter) SetBurstAt(now time.Time, newBurst int) { 332 lim.mu.Lock() 333 defer lim.mu.Unlock() 334 335 now, _, tokens := lim.advance(now) 336 337 lim.last = now 338 lim.tokens = tokens 339 lim.burst = newBurst 340 } 341 342 // reserveN is a helper method for AllowN, ReserveN, and WaitN. 343 // maxFutureReserve specifies the maximum reservation wait duration allowed. 344 // reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN. 345 func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation { 346 lim.mu.Lock() 347 348 if lim.limit == Inf { 349 lim.mu.Unlock() 350 return Reservation{ 351 ok: true, 352 lim: lim, 353 tokens: n, 354 timeToAct: now, 355 } 356 } 357 358 now, last, tokens := lim.advance(now) 359 360 // Calculate the remaining number of tokens resulting from the request. 361 tokens -= float64(n) 362 363 // Calculate the wait duration 364 var waitDuration time.Duration 365 if tokens < 0 { 366 waitDuration = lim.limit.durationFromTokens(-tokens) 367 } 368 369 // Decide result 370 ok := n <= lim.burst && waitDuration <= maxFutureReserve 371 372 // Prepare reservation 373 r := Reservation{ 374 ok: ok, 375 lim: lim, 376 limit: lim.limit, 377 } 378 if ok { 379 r.tokens = n 380 r.timeToAct = now.Add(waitDuration) 381 } 382 383 // Update state 384 if ok { 385 lim.last = now 386 lim.tokens = tokens 387 lim.lastEvent = r.timeToAct 388 } else { 389 lim.last = last 390 } 391 392 lim.mu.Unlock() 393 return r 394 } 395 396 // advance calculates and returns an updated state for lim resulting from the passage of time. 397 // lim is not changed. 398 func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) { 399 last := lim.last 400 if now.Before(last) { 401 last = now 402 } 403 404 // Avoid making delta overflow below when last is very old. 405 maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens) 406 elapsed := now.Sub(last) 407 if elapsed > maxElapsed { 408 elapsed = maxElapsed 409 } 410 411 // Calculate the new number of tokens, due to time that passed. 412 delta := lim.limit.tokensFromDuration(elapsed) 413 tokens := lim.tokens + delta 414 if burst := float64(lim.burst); tokens > burst { 415 tokens = burst 416 } 417 418 return now, last, tokens 419 } 420 421 // durationFromTokens is a unit conversion function from the number of tokens to the duration 422 // of time it takes to accumulate them at a rate of limit tokens per second. 423 func (limit Limit) durationFromTokens(tokens float64) time.Duration { 424 seconds := tokens / float64(limit) 425 return time.Nanosecond * time.Duration(1e9*seconds) 426 } 427 428 // tokensFromDuration is a unit conversion function from a time duration to the number of tokens 429 // which could be accumulated during that duration at a rate of limit tokens per second. 430 func (limit Limit) tokensFromDuration(d time.Duration) float64 { 431 // Split the integer and fractional parts ourself to minimize rounding errors. 432 // See golang.org/issues/34861. 433 sec := float64(d/time.Second) * float64(limit) 434 nsec := float64(d%time.Second) * float64(limit) 435 return sec + nsec/1e9 436 } 437 438 //return the number of token available in the bucket 439 func (lim *Limiter) GetTokensCount() float64 { 440 _, _, tokens := lim.advance(time.Now()) 441 return tokens 442 } 443 444 //return the number of token available in the bucket 445 func (lim *Limiter) GetTokensCountAt(t time.Time) float64 { 446 _, _, tokens := lim.advance(t) 447 return tokens 448 } 449 450 //A rate limiter that doesn't limit anything 451 //this is compliant to the earlier interface 452 type AlwaysFull struct { 453 } 454 455 func (af *AlwaysFull) Dump() Lstate { 456 return Lstate{} 457 } 458 459 func (af *AlwaysFull) Load(st Lstate) { 460 return 461 } 462 463 func (af *AlwaysFull) Allow() bool { 464 return true 465 } 466 467 func (af *AlwaysFull) AllowN(time.Time, int) bool { 468 return true 469 } 470 471 func (af *AlwaysFull) GetTokensCount() float64 { 472 return float64(int(^uint(0) >> 1)) 473 } 474 475 func (af *AlwaysFull) GetTokensCountAt(t time.Time) float64 { 476 return float64(int(^uint(0) >> 1)) 477 }