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  }