Documentation
¶
Index ¶
- Variables
- func IsRedisDown(err error) bool
- type FixedWindowLimiter
- type GCRALimiter
- type InMemoryFixedWindow
- type InMemoryGCRA
- type InMemorySlidingWindowCounter
- type InMemorySlidingWindowLog
- type InMemoryTokenBucket
- type Limiter
- type Logger
- type NopLogger
- type Option
- type Options
- type RedisClient
- type Result
- type SlidingWindowCounterLimiter
- type SlidingWindowLogLimiter
- type TokenBucketLimiter
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidLimit = errors.New("fluxrate: limit must be greater than zero") ErrInvalidWindow = errors.New("fluxrate: window duration must be greater than zero") )
Functions ¶
func IsRedisDown ¶
Types ¶
type FixedWindowLimiter ¶
type FixedWindowLimiter struct {
// contains filtered or unexported fields
}
func NewFixedWindow ¶
type GCRALimiter ¶
type GCRALimiter struct {
// contains filtered or unexported fields
}
func (*GCRALimiter) Allow ¶
* Allow evaluates the rate limit via Redis Lua script, failing over to local in-memory fallback on error. * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining quota and reset durations, and an error.
type InMemoryFixedWindow ¶
type InMemoryFixedWindow struct {
// contains filtered or unexported fields
}
func NewInMemoryFixedWindow ¶
func NewInMemoryFixedWindow(limit int64, window time.Duration) *InMemoryFixedWindow
type InMemoryGCRA ¶
type InMemoryGCRA struct {
// contains filtered or unexported fields
}
func NewInMemoryGCRA ¶
func NewInMemoryGCRA(rateLimit int64, period time.Duration) *InMemoryGCRA
func (*InMemoryGCRA) Allow ¶
* Allow evaluates the rate limit locally using the GCRA (Generic Cell Rate Algorithm): * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining quota and reset durations, and an error. * * @note Mathematics of GCRA: * 1. Emission Interval (T) = period / rateLimit. (Perfect spacing between requests). * 2. Burst Tolerance (tau) = period. (Allows requests to arrive in bursts up to the period size). * 3. We calculate newTAT = max(oldTAT, now) + T. * 4. If newTAT - now > tau, the rate limit is exceeded. The request is rejected, and the client * must wait for (newTAT - tau - now) before retrying. * 5. If allowed, we update TAT = newTAT.
type InMemorySlidingWindowCounter ¶
type InMemorySlidingWindowCounter struct {
// contains filtered or unexported fields
}
func NewInMemorySlidingWindowCounter ¶
func NewInMemorySlidingWindowCounter(limit int64, window time.Duration) *InMemorySlidingWindowCounter
func (*InMemorySlidingWindowCounter) Allow ¶
* Allow evaluates the rate limit locally using the Sliding Window Counter algorithm: * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining requests and reset durations, and an error. * * @note Weighted-Average Approximation: * 1. Time is partitioned into fixed window slots (e.g. 1-minute blocks). * 2. We keep track of the request count in the current block (currCount) and the previous block (prevCount). * 3. We calculate the percentage progress through the current block: * weight = (windowMs - elapsedMsInCurrentBlock) / windowMs * 4. We approximate the request count in the sliding window as: * estimatedCount = prevCount * weight + currCount * 5. This achieves ~99% accuracy with O(1) memory footprint.
type InMemorySlidingWindowLog ¶
type InMemorySlidingWindowLog struct {
// contains filtered or unexported fields
}
func NewInMemorySlidingWindowLog ¶
func NewInMemorySlidingWindowLog(limit int64, window time.Duration) *InMemorySlidingWindowLog
type InMemoryTokenBucket ¶
type InMemoryTokenBucket struct {
// contains filtered or unexported fields
}
func NewInMemoryTokenBucket ¶
func NewInMemoryTokenBucket(capacity int64, refillRateSec float64) *InMemoryTokenBucket
func (*InMemoryTokenBucket) Allow ¶
* Allow evaluates the rate limit locally using the Token Bucket state logic: * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining tokens and reset durations, and an error. * * @note Mathematics of Token Bucket: * 1. Tokens are replenished continuously over time based on the elapsed duration: * tokens = min(capacity, currentTokens + elapsedSeconds * refillRatePerSecond) * 2. If the current token count is less than the requested cost (default 1), * the request is blocked, and we return the time to wait until enough tokens refill. * 3. Otherwise, we deduct the tokens and return Allowed with the remaining token count.
type Option ¶
type Option func(*Options)
func WithFallbackOnErr ¶
func WithKeyPrefix ¶
func WithLocalFallback ¶
func WithLogger ¶
type Options ¶
func DefaultOptions ¶
func DefaultOptions() Options
type RedisClient ¶
func NewRedis ¶
func NewRedis(addr string) *RedisClient
type Result ¶
type Result struct {
Allowed bool
Limit int64
Remaining int64
ResetAfter time.Duration
RetryAfter time.Duration
}
* Result represents the final evaluation status of a rate limit check. * * @field Allowed - True if the request is permitted, false if blocked. * @field Limit - The maximum number of requests allowed in the configured window. * @field Remaining - The remaining quota in the current window. * @field ResetAfter - Duration remaining until the rate limit window resets/refills. * @field RetryAfter - Time duration the client must wait before retrying (only set if Allowed is false).
type SlidingWindowCounterLimiter ¶
type SlidingWindowCounterLimiter struct {
// contains filtered or unexported fields
}
func NewSlidingWindowCounter ¶
func (*SlidingWindowCounterLimiter) Allow ¶
* Allow evaluates the rate limit via Redis, failing over to local in-memory fallback on error. * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining requests and reset durations, and an error.
type SlidingWindowLogLimiter ¶
type SlidingWindowLogLimiter struct {
// contains filtered or unexported fields
}
func NewSlidingWindowLog ¶
func (*SlidingWindowLogLimiter) Allow ¶
* Allow evaluates the rate limit via Redis Sorted Sets (ZSET): * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining requests and reset durations, and an error. * * @note Unique member generation: * In a ZSET sliding window, the score is the timestamp, and we store every request. * Since Redis sorted set members must be unique, we generate a unique member value * by concatenating the nanosecond timestamp with a random suffix. This guarantees * that concurrent requests from the same user at the exact same millisecond score * are all recorded uniquely.
type TokenBucketLimiter ¶
type TokenBucketLimiter struct {
// contains filtered or unexported fields
}
func NewTokenBucket ¶
func (*TokenBucketLimiter) Allow ¶
* Allow evaluates the rate limit via Redis hashes, failing over to local in-memory fallback on error. * * @param ctx - The execution context for cancellation and timeouts. * @param key - The unique client identifier (e.g. API key, IP address). * @return A Result pointer with remaining tokens and reset durations, and an error.