ratelimit

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package ratelimit is a token-bucket rate limiter for forge services.

A Limiter decides whether a keyed caller may proceed under a Policy (limit per window + burst). Keys are caller-defined: per org, per API key, per client IP, or — in Conduit — per upstream provider so a fleet of tenants can't collectively trip an exchange's API limits.

The token-bucket math lives in the Store, so the in-memory store guards it with a mutex and a future Redis store can do it atomically in Lua for multi-replica correctness. HTTP middleware and a gRPC interceptor wire a Limiter onto a transport with the standard RateLimit-* / Retry-After headers and a 429 on denial.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FxModule

func FxModule() fx.Option

FxModule provides a process-local Limiter. Services build their HTTP middleware / gRPC interceptor from it with a KeyFunc + Policy.

func OrgKey

func OrgKey(ctx context.Context) string

OrgKey keys a call on the active organization claim.

func UnaryInterceptor

func UnaryInterceptor(l Limiter, key CtxKeyFunc, policy Policy) grpc.UnaryServerInterceptor

UnaryInterceptor enforces a Limiter on unary gRPC calls; a denied call returns a RateLimited error (mapped to ResourceExhausted by the kit).

Types

type CtxKeyFunc

type CtxKeyFunc func(context.Context) string

CtxKeyFunc derives the bucket key from a gRPC call's context.

type HTTPMiddleware

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

HTTPMiddleware enforces a Limiter on an HTTP handler chain.

func NewHTTPMiddleware

func NewHTTPMiddleware(l Limiter, key KeyFunc, policy PolicyFunc) *HTTPMiddleware

NewHTTPMiddleware builds the middleware. It implements the kit rest Middleware interface (Intercept).

func (*HTTPMiddleware) Intercept

func (m *HTTPMiddleware) Intercept(next http.Handler) http.Handler

type KeyFunc

type KeyFunc func(*http.Request) string

KeyFunc derives the rate-limit bucket key from a request.

func ByIP

func ByIP() KeyFunc

ByIP keys on the client IP.

func ByOrg

func ByOrg() KeyFunc

ByOrg keys on the active organization claim, falling back to client IP.

type Limiter

type Limiter interface {
	// Allow consumes one token for key under policy.
	Allow(ctx context.Context, key string, policy Policy) (Result, error)
	// AllowN consumes cost tokens (e.g. an expensive endpoint costs more).
	AllowN(ctx context.Context, key string, policy Policy, cost int) (Result, error)
}

Limiter checks a keyed caller against a Policy.

func New

func New(store Store, opts ...Option) Limiter

New builds a Limiter over the given Store (use NewInMemoryStore for the default process-local backend).

type Option

type Option func(*limiter)

Option configures a Limiter.

func WithClock

func WithClock(now func() time.Time) Option

WithClock overrides the time source (tests).

type Policy

type Policy struct {
	Limit  int
	Window time.Duration
	Burst  int
}

Policy is a token-bucket rate: Limit tokens refilled over Window, with a bucket capacity of Burst (defaults to Limit when zero).

func (Policy) Capacity

func (p Policy) Capacity() float64

Capacity is the bucket size (Burst, or Limit when Burst is unset).

func (Policy) RefillPerSecond

func (p Policy) RefillPerSecond() float64

RefillPerSecond is how fast tokens are replenished.

type PolicyFunc

type PolicyFunc func(*http.Request) Policy

PolicyFunc resolves the policy for a request (e.g. by tier/route).

func StaticPolicy

func StaticPolicy(p Policy) PolicyFunc

StaticPolicy always yields p.

type Result

type Result struct {
	Allowed    bool
	Limit      int           // Policy.Limit, for the RateLimit-Limit header
	Remaining  int           // whole tokens left after this call
	ResetAfter time.Duration // until the bucket refills to full
	RetryAfter time.Duration // until cost tokens are available again (deny only)
}

Result is the outcome of a limit check.

type Store

type Store interface {
	Take(ctx context.Context, key string, policy Policy, cost int, now time.Time) (Result, error)
}

Store holds bucket state and performs the atomic take. Implementations: in-memory (mutex) now; Redis (Lua) later for multi-replica correctness.

func NewInMemoryStore

func NewInMemoryStore() Store

NewInMemoryStore returns a process-local token-bucket Store.

Jump to

Keyboard shortcuts

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