Throttle Stability Pattern

Table of Contents

  • limits the frequency of a funciton call to some maximum number of invocations per minute
  • See Rate Limiting Algorithms
  • diff w/ Debounce
    • debounce collates clusters of calls (across flexible durations) into representative boundary calls
    • throttle limits the amount of calls in a relatively fixed duration
  • 2 components
    • Effector : the function being regulated
    • Throttle : the enwrapping closure over Effector : implementing the rate limiting layer

1. Code

type Effector func(context.Context) (string, error)
func Throttle(e Effector, max uint, refill uint, d time.Duration) Effector {
        var tokens = max
        var once sync.Once

        return func(ctx context.Context) (string, error) {
                if ctx.Err() != nil {
                        return "", ctx.Err()
                }
        }

        once.Do(func() {
                ticker := time.NewTicker(d)

                go func() {
                        defer ticker.Stop()

                        for {
                                select {
                                case <-ctx.Done():
                                        return

                                case <- ticker.C:
                                        t := tokens + refill
                                        if t > max {
                                                t = max
                                        }
                                        tokens = t
                                }
                        }
                }()
        })

        if tokens <= 0 {
                return "", fmt.Errorf("too many calls")
        }

        tokens--

        return e(ctx)
}
Tags::cloud:cs: