tokenbucket

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrExceedsBucketCapacity = errors.New("request exceeds bucket capacity")

ErrExceedsBucketCapacity means the number of tokens requested from the limiter exceeds the capacity of the bucket and therefore can never be satisfied

Functions

This section is empty.

Types

type CacheableKeyedLimiter

type CacheableKeyedLimiter interface {
	Allow(ctx context.Context, key string) (ok bool, wait time.Duration, err error)
}

type CacheableLimiter

type CacheableLimiter interface {
	Allow(ctx context.Context) (ok bool, wait time.Duration, err error)
}

type KeyedLimiter

type KeyedLimiter interface {
	CacheableKeyedLimiter

	AllowN(ctx context.Context, key string, n int) (ok bool, wait time.Duration, err error)

	Replenish(ctx context.Context, key string) error
	ReplenishN(ctx context.Context, key string, n int) error
}

type Limiter

type Limiter interface {
	CacheableLimiter

	AllowN(ctx context.Context, n int) (ok bool, wait time.Duration, err error)

	Replenish(ctx context.Context) error
	ReplenishN(ctx context.Context, n int) error
}

type LimiterOpts

type LimiterOpts struct {
	// RatePerSec is the replenish rate of the bucket.
	// i.e. how many tokens get deposited in the bucket per second.
	// Required.
	RatePerSec float64

	// Capacity is the bucket's maximum capacity.
	// Buckets start full.
	// Required.
	Capacity int
}

func (*LimiterOpts) Sanitize

func (o *LimiterOpts) Sanitize() error

type LocalKeyedLimiter

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

LocalKeyedLimiter manages in-memory token buckets and uses the same semantics as the redis-backed ReplenishableKeyedLimiter.

As with redis KeyedLimiter, only non-full buckets are kept in memory

func NewLocalKeyedLimiter

func NewLocalKeyedLimiter(opts LimiterOpts) (*LocalKeyedLimiter, error)

func (*LocalKeyedLimiter) Allow

func (l *LocalKeyedLimiter) Allow(ctx context.Context, key string) (ok bool, wait time.Duration, err error)

func (*LocalKeyedLimiter) AllowN

func (l *LocalKeyedLimiter) AllowN(_ context.Context, key string, n int) (ok bool, wait time.Duration, err error)

func (*LocalKeyedLimiter) Replenish

func (l *LocalKeyedLimiter) Replenish(ctx context.Context, key string) error

func (*LocalKeyedLimiter) ReplenishN

func (l *LocalKeyedLimiter) ReplenishN(ctx context.Context, key string, n int) error

type LocalLimiter

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

LocalLimiter is an in-memory token bucket that uses the same semantics as the redis-backed Limiter

func NewLocalLimiter

func NewLocalLimiter(opts *LimiterOpts) (*LocalLimiter, error)

func (*LocalLimiter) Allow

func (l *LocalLimiter) Allow(ctx context.Context) (ok bool, wait time.Duration, err error)

func (*LocalLimiter) AllowN

func (l *LocalLimiter) AllowN(_ context.Context, n int) (ok bool, wait time.Duration, err error)

func (*LocalLimiter) Replenish

func (l *LocalLimiter) Replenish(ctx context.Context) error

func (*LocalLimiter) ReplenishN

func (l *LocalLimiter) ReplenishN(ctx context.Context, n int) error

type RedisCacheableKeyedLimiter

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

RedisCacheableKeyedLimiter is a non-replenishable limiter that caches wait durations to avoid unnecessary redis calls.

If an earlier call to Allow was unsuccessful due to an empty bucket, it returns the wait time until the next token will be available. The limiter won't make further round-trips to redis until the wait time has elapsed.

func NewRedisCacheableKeyedLimiter

func NewRedisCacheableKeyedLimiter(client rueidis.Client, opts RedisKeyedLimiterOpts) (*RedisCacheableKeyedLimiter, error)

NewRedisCacheableKeyedLimiter instantiates the limiter and starts a goroutine to clean up expired wait cache items. Call Stop when done.

func (*RedisCacheableKeyedLimiter) Allow

func (l *RedisCacheableKeyedLimiter) Allow(ctx context.Context, key string) (ok bool, wait time.Duration, err error)

type RedisCacheableLimiter

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

RedisCacheableLimiter is a convenience wrapper around a RedisCacheableKeyedLimiter that limits a single default key Caches wait times when the limiter is exhausted.

func NewRedisCacheableLimiter

func NewRedisCacheableLimiter(client rueidis.Client, opts RedisLimiterOpts) (*RedisCacheableLimiter, error)

func (*RedisCacheableLimiter) Allow

func (l *RedisCacheableLimiter) Allow(ctx context.Context) (ok bool, wait time.Duration, err error)

type RedisKeyedLimiter

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

RedisKeyedLimiter is a redis-backed token bucket rate limiter that supports attempting to take tokens from the bucket AND replenishing tokens back into the bucket.

Allow/Replenish take a key used to identify an individual resource. This allows a single limiter instance to limit multiple an action for multiple different actors, e.g. limiting a common action (id: api_endpoint) on a per-actor basis (key: ip_address).

Using the same opts allows multiple machines to participate in the same limiter.

Each call to AllowN and ReplenishN is a round-trip to redis -- there is no caching. All keys written to Redis expire via PX, and the "full bucket" state is reflected with no keys existing in redis.

Use RedisCacheableKeyedLimiter instead for scenarios where replenishment and taking multiple tokens aren't needed, as KeyedLimiter can cache client-side.

func NewRedisKeyedLimiter

func NewRedisKeyedLimiter(client rueidis.Client, opts RedisKeyedLimiterOpts) (*RedisKeyedLimiter, error)

func (*RedisKeyedLimiter) Allow

func (l *RedisKeyedLimiter) Allow(ctx context.Context, key string) (ok bool, wait time.Duration, err error)

func (*RedisKeyedLimiter) AllowN

func (l *RedisKeyedLimiter) AllowN(ctx context.Context, key string, n int) (ok bool, wait time.Duration, err error)

func (*RedisKeyedLimiter) Replenish

func (l *RedisKeyedLimiter) Replenish(ctx context.Context, key string) error

func (*RedisKeyedLimiter) ReplenishN

func (l *RedisKeyedLimiter) ReplenishN(ctx context.Context, key string, n int) error

type RedisKeyedLimiterOpts

type RedisKeyedLimiterOpts struct {
	LimiterOpts LimiterOpts

	// RedisKey is the Redis key where the limiter state score should be stored
	// for a given limiter key, e.g. limiter:users_by_ip:{key}
	RedisKey func(key string) string
}

func DefaultRedisKeyedLimiterOpts

func DefaultRedisKeyedLimiterOpts(name string, opts LimiterOpts) RedisKeyedLimiterOpts

DefaultRedisKeyedLimiterOpts creates a config that writes to the Redis key "limiter:name:{key}"

func (*RedisKeyedLimiterOpts) Sanitize

func (o *RedisKeyedLimiterOpts) Sanitize() error

type RedisLimiter

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

RedisLimiter is a convenience wrapper around a RedisKeyedLimiter that limits a single default key

func NewRedisLimiter

func NewRedisLimiter(client rueidis.Client, opts RedisLimiterOpts) (*RedisLimiter, error)

func (*RedisLimiter) Allow

func (l *RedisLimiter) Allow(ctx context.Context) (ok bool, wait time.Duration, err error)

func (*RedisLimiter) AllowN

func (l *RedisLimiter) AllowN(ctx context.Context, n int) (ok bool, wait time.Duration, err error)

func (*RedisLimiter) Replenish

func (l *RedisLimiter) Replenish(ctx context.Context) error

func (*RedisLimiter) ReplenishN

func (l *RedisLimiter) ReplenishN(ctx context.Context, n int) error

type RedisLimiterOpts

type RedisLimiterOpts struct {
	LimiterOpts LimiterOpts

	// RedisKey is the Redis key where the limiter state should be stored,
	// e.g. limiter:{my_global_action}
	RedisKey string
}

func DefaultRedisLimiterOpts

func DefaultRedisLimiterOpts(name string, opts LimiterOpts) RedisLimiterOpts

DefaultRedisLimiterOpts creates a config that writes to the Redis key "limiter:name"

func (*RedisLimiterOpts) Sanitize

func (o *RedisLimiterOpts) Sanitize() error

Jump to

Keyboard shortcuts

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