Documentation
¶
Overview ¶
Package ratelimit supplies typed, atomic fixed-window admission decisions.
Index ¶
- Constants
- func ValidateClear(ctx context.Context, key Key) error
- func ValidateOperation(ctx context.Context, key Key, limit Limit, cost uint32) error
- type Backend
- type Config
- type Decision
- type Declaration
- type InspectBackend
- type Key
- type Limit
- type Limiter
- func (l Limiter[K]) Allow(ctx context.Context, key K) (Decision, error)
- func (l Limiter[K]) Attempt(ctx context.Context, key K, cost uint32, fn func(context.Context) error) (Decision, error)
- func (l Limiter[K]) AvailableIn(ctx context.Context, key K, cost uint32) (time.Duration, error)
- func (l Limiter[K]) Clear(ctx context.Context, key K) (bool, error)
- func (l Limiter[K]) Limit() Limit
- func (l Limiter[K]) Name() Name
- func (l Limiter[K]) Peek(ctx context.Context, key K, cost uint32) (Decision, error)
- func (l Limiter[K]) Remaining(ctx context.Context, key K) (uint32, error)
- func (l Limiter[K]) Take(ctx context.Context, key K, cost uint32) (Decision, error)
- func (l Limiter[K]) TakeWith(ctx context.Context, cost uint32, resolve func(context.Context) (K, error)) (Decision, error)
- func (l Limiter[K]) Validate() error
- type Name
- type Store
Constants ¶
const KeyFeature keyspace.Feature = "ratelimit"
KeyFeature is the physical address family owned by this adapter.
const MaxWindow = 24 * time.Hour
MaxWindow bounds live policy retention and retry durations.
Variables ¶
This section is empty.
Functions ¶
func ValidateClear ¶
ValidateClear shares the adapter input boundary for ClearRateLimit.
Types ¶
type Backend ¶
Backend owns one authority's clock and atomic fixed-window decisions. A live bucket with a different policy is converted to the requested one: admitted usage still counts (capped at the new capacity) and a new window starts on the new policy's phase. Denials consume nothing; a denied take persists only a conversion that ends later than the live bucket, so carried usage is never released early. Windows use Key.WindowOffset. A backward clock step inside a live bucket is clamped to that bucket's start instead of reopening quota or failing. Implementations honor cancellation, bound metadata reads and never implicitly retry a mutation or fall back to another authority. The caller owns the adapter lifecycle; network errors may leave consumption unconfirmed.
type Config ¶
type Config struct {
Namespace keyspace.Namespace
MaxKeyBytes, MaxDeclarations, MaxConcurrent int
Timeout time.Duration
}
Config bounds declaration count, logical key bytes and entire active operations, including key resolvers/codecs. Timeout uses real context deadlines. A burst beyond MaxConcurrent waits in FIFO order for at most admission.Wait(Timeout), within that same deadline, and then fails with fault.Overloaded.
func DefaultConfig ¶
type Decision ¶
Decision reports the authority's decision at execution time. Denials consume no capacity. Durations are relative to that decision, not the client clock. An error always returns a zero Decision; never infer admission from an error.
type Declaration ¶
type Declaration[K any] struct { // contains filtered or unexported fields }
Declaration preserves its resource key type and immutable policy. Reuse one declaration for a shared quota; distinct names intentionally isolate quotas.
func (Declaration[K]) Bind ¶
func (d Declaration[K]) Bind(store *Store) (Limiter[K], error)
Bind rejects a different declaration with the same name, even with identical K.
func (Declaration[K]) Limit ¶
func (d Declaration[K]) Limit() Limit
func (Declaration[K]) Name ¶
func (d Declaration[K]) Name() Name
func (Declaration[K]) Validate ¶
func (d Declaration[K]) Validate() error
type InspectBackend ¶
type InspectBackend interface {
PeekRateLimit(context.Context, Key, Limit, uint32) (Decision, error)
ClearRateLimit(context.Context, Key) (bool, error)
}
InspectBackend is an optional Backend capability. PeekRateLimit reports the decision cost would receive now, using the same policy conversion and clock rules, without consuming capacity or changing expiry; see Decision.ValidatePeek. ClearRateLimit removes the key's bucket, including unreadable state at its address, so the next request starts a fresh window; true means state existed. Both follow Backend's cancellation, validation and no-retry rules.
type Key ¶
type Key struct {
// contains filtered or unexported fields
}
Key is an opaque adapter address, distinct from cache and lease keys.
func (Key) WindowOffset ¶
WindowOffset is this key's deterministic window phase in [0, window). Adapters start fixed windows at offset + n*window, so the buckets of many keys do not all reset at the same Unix-epoch boundary. Every authority derives the same offset from the key address, independent of process or client clock. An uninitialized key or a nonpositive window has no phase.
type Limit ¶
Limit admits Requests units per fixed Window. Each key's windows are shifted by its Key.WindowOffset, so many keys do not reset at the same instant. A fixed window permits bursts on both sides of a boundary; it is not a sliding window.
func (Limit) ValidateCost ¶
type Limiter ¶
type Limiter[K any] struct { // contains filtered or unexported fields }
Limiter consumes capacity using only its declaration's key type. Its zero value is invalid. Take is appropriate for weighted domain work; Allow costs one unit.
func (Limiter[K]) Attempt ¶
func (l Limiter[K]) Attempt(ctx context.Context, key K, cost uint32, fn func(context.Context) error) (Decision, error)
Attempt takes cost and runs fn only when admitted, returning fn's error. A denial returns the decision without calling fn; an admission error returns it without calling fn. fn runs in the caller's goroutine after the bounded admission operation has finished, with the caller's context. Consumed capacity is not refunded when fn fails, and nothing is retried.
func (Limiter[K]) AvailableIn ¶
AvailableIn reports how long until cost could be admitted: zero when it fits now, otherwise the time until the current window resets. It consumes nothing.
func (Limiter[K]) Clear ¶
Clear removes the key's bucket so its next request starts a fresh window with full capacity. True means stored state existed. It also removes unreadable state at the key's address. Clearing grants new quota; use it deliberately (for example after a successful verification), never as error recovery.
func (Limiter[K]) Peek ¶
Peek reports the decision cost would receive now without consuming capacity or changing the bucket's expiry. Remaining is the capacity left now. It is an observation, not a reservation: a later Take can be denied. The backend must implement InspectBackend; otherwise Peek fails with fault.Invalid.
func (Limiter[K]) Remaining ¶
Remaining reports the capacity left in the key's current window without consuming it. A missing or expired bucket reports the full capacity.
func (Limiter[K]) TakeWith ¶
func (l Limiter[K]) TakeWith(ctx context.Context, cost uint32, resolve func(context.Context) (K, error)) (Decision, error)
TakeWith resolves a concrete key inside the same bounded operation as encoding and admission. It catches panic/Goexit and waits for callback exit. The resolver must honor cancellation; no callback or uncertain command is automatically retried.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store borrows its Backend. Construction performs no I/O or background work. Calls own callbacks until they actually exit, including after cancellation; an uncooperative callback retains its slot instead of creating detached work.