rate

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2025 License: MIT Imports: 10 Imported by: 0

README

Rate Limiter Package

The rate package provides a generic implementation of a token bucket rate limiter to protect resources from being overwhelmed by too many requests.

Overview

Rate limiting is a strategy to control the rate of requests sent or received by a system. It helps prevent resource exhaustion, maintain service quality, and ensure fair usage of shared resources.

This implementation provides:

  • Generic support for any function that returns a value and an error
  • Token bucket algorithm for precise rate limiting
  • Configurable requests per second and burst size
  • Support for both immediate rejection and waiting for available tokens
  • Support for OpenTelemetry tracing
  • Fluent interface for configuration
  • Thread-safe implementation

Usage

Basic Usage
import (
    "context"
    "github.com/abitofhelp/servicelib/rate"
    "github.com/abitofhelp/servicelib/logging"
    "go.uber.org/zap"
)

// Create a rate limiter
cfg := rate.DefaultConfig().
    WithEnabled(true).
    WithRequestsPerSecond(100).
    WithBurstSize(50)

logger := logging.NewContextLogger(zap.NewNop())
options := rate.DefaultOptions().
    WithName("my-service").
    WithLogger(logger)

rl := rate.NewRateLimiter(cfg, options)

// Execute a function with rate limiting
result, err := rate.Execute(ctx, rl, "GetUserProfile", func(ctx context.Context) (UserProfile, error) {
    // Call external service
    return userService.GetProfile(ctx, userID)
})

// If the rate limit is exceeded, an error will be returned
if err != nil {
    // Handle rate limit exceeded error
    return nil, err
}

// Use the result
return result, nil
With Wait

If you want to wait for a token to become available instead of immediately rejecting the request:

// Execute a function with rate limiting and wait for a token
result, err := rate.ExecuteWithWait(ctx, rl, "GetUserProfile", func(ctx context.Context) (UserProfile, error) {
    // Call external service
    return userService.GetProfile(ctx, userID)
})

// If the context is canceled while waiting, an error will be returned
if err != nil {
    // Handle context cancellation
    return nil, err
}

// Use the result
return result, nil

Configuration

The rate limiter can be configured using the Config struct and the fluent interface:

cfg := rate.DefaultConfig().
    WithEnabled(true).                  // Enable/disable the rate limiter
    WithRequestsPerSecond(100).         // Number of requests allowed per second
    WithBurstSize(50)                   // Maximum number of requests allowed in a burst

OpenTelemetry Integration

The rate limiter supports OpenTelemetry tracing:

import (
    "go.opentelemetry.io/otel/trace"
)

// Create a tracer
tracer := otelTracer // Your OpenTelemetry tracer

// Configure the rate limiter with the tracer
options := rate.DefaultOptions().
    WithName("my-service").
    WithLogger(logger).
    WithOtelTracer(tracer)

rl := rate.NewRateLimiter(cfg, options)

Thread Safety

The rate limiter is thread-safe and can be used concurrently from multiple goroutines.

Performance Considerations

  • The token bucket algorithm provides precise rate limiting with minimal overhead
  • Tokens are refilled based on the time elapsed since the last refill, ensuring accurate rate limiting
  • The rate limiter uses a mutex to ensure thread safety, so concurrent operations are serialized
  • The ExecuteWithWait method uses a polling approach with a small sleep interval, which may not be optimal for high-concurrency scenarios

Documentation

Overview

Package rate provides functionality for rate limiting to protect resources.

This package implements a token bucket rate limiter to protect resources from being overwhelmed by too many requests.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Execute

func Execute[T any](ctx context.Context, rl *RateLimiter, operation string, fn func(ctx context.Context) (T, error)) (T, error)

Execute executes the given function with rate limiting If the rate limit is exceeded, it will return an error immediately Otherwise, it will execute the function

func ExecuteWithWait

func ExecuteWithWait[T any](ctx context.Context, rl *RateLimiter, operation string, fn func(ctx context.Context) (T, error)) (T, error)

ExecuteWithWait executes the given function with rate limiting If the rate limit is exceeded, it will wait until a token is available and then execute the function

Types

type Config

type Config struct {
	// Enabled determines if the rate limiter is enabled
	Enabled bool
	// RequestsPerSecond is the number of requests allowed per second
	RequestsPerSecond int
	// BurstSize is the maximum number of requests allowed in a burst
	BurstSize int
}

Config contains rate limiter configuration parameters

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a default rate limiter configuration

func (Config) WithBurstSize

func (c Config) WithBurstSize(burstSize int) Config

WithBurstSize sets the maximum number of requests allowed in a burst

func (Config) WithEnabled

func (c Config) WithEnabled(enabled bool) Config

WithEnabled sets whether the rate limiter is enabled

func (Config) WithRequestsPerSecond

func (c Config) WithRequestsPerSecond(requestsPerSecond int) Config

WithRequestsPerSecond sets the number of requests allowed per second

type Options

type Options struct {
	// Logger is used for logging rate limiter operations
	Logger *logging.ContextLogger
	// Tracer is used for tracing rate limiter operations
	Tracer telemetry.Tracer
	// Name is the name of the rate limiter
	Name string
}

Options contains additional options for the rate limiter

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns default options for rate limiter operations

func (Options) WithLogger

func (o Options) WithLogger(logger *logging.ContextLogger) Options

WithLogger sets the logger for the rate limiter

func (Options) WithName

func (o Options) WithName(name string) Options

WithName sets the name of the rate limiter

func (Options) WithOtelTracer

func (o Options) WithOtelTracer(tracer trace.Tracer) Options

WithOtelTracer returns Options with an OpenTelemetry tracer

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter implements a token bucket rate limiter to protect resources from being overwhelmed by too many requests.

func NewRateLimiter

func NewRateLimiter(config Config, options Options) *RateLimiter

NewRateLimiter creates a new rate limiter

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow() bool

Allow checks if a request should be allowed based on the rate limit It returns true if the request is allowed, false otherwise

func (*RateLimiter) Reset

func (rl *RateLimiter) Reset()

Reset resets the rate limiter to its initial state

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL