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