limited

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package limited provides DynamoDB-backed rate limiting for AppTheory.

This package replicates the core functionality of `github.com/pay-theory/limited`, but uses TableTheory as the DynamoDB abstraction.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AtomicRateLimiter

type AtomicRateLimiter interface {
	RateLimiter

	// CheckAndIncrement performs an atomic check-and-increment operation.
	CheckAndIncrement(ctx context.Context, key RateLimitKey) (*LimitDecision, error)
}

AtomicRateLimiter is a RateLimiter that can atomically check and increment.

type Clock

type Clock interface {
	Now() time.Time
}

Clock allows deterministic testing of time-sensitive logic.

type Config

type Config struct {
	DefaultRequestsPerHour   int
	DefaultRequestsPerMinute int
	DefaultBurstCapacity     int

	EnableBurstCapacity bool
	EnableSoftLimits    bool
	FailOpen            bool

	// TableName is kept for configuration parity; TableTheory table names are derived
	// from model metadata, so callers should set table name via environment before use.
	TableName      string
	ConsistentRead bool
	TTLHours       int

	IdentifierLimits map[string]Limit
	ResourceLimits   map[string]Limit
}

Config contains configuration for the rate limiter.

func DefaultConfig

func DefaultConfig() *Config

type DynamoRateLimiter

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

DynamoRateLimiter implements RateLimiter using DynamoDB via TableTheory.

func NewDynamoRateLimiter

func NewDynamoRateLimiter(db tablecore.DB, config *Config, strategy RateLimitStrategy) *DynamoRateLimiter

func (*DynamoRateLimiter) CheckAndIncrement

func (r *DynamoRateLimiter) CheckAndIncrement(ctx context.Context, key RateLimitKey) (*LimitDecision, error)

func (*DynamoRateLimiter) CheckLimit

func (r *DynamoRateLimiter) CheckLimit(ctx context.Context, key RateLimitKey) (*LimitDecision, error)

func (*DynamoRateLimiter) GetUsage

func (r *DynamoRateLimiter) GetUsage(ctx context.Context, key RateLimitKey) (*UsageStats, error)

func (*DynamoRateLimiter) RecordRequest

func (r *DynamoRateLimiter) RecordRequest(ctx context.Context, key RateLimitKey) error

func (*DynamoRateLimiter) SetClock

func (r *DynamoRateLimiter) SetClock(clock Clock)

func (*DynamoRateLimiter) String

func (r *DynamoRateLimiter) String() string

type Error

type Error struct {
	Type    ErrorType
	Message string
	Cause   error
}

Error represents a rate limiter error.

func NewError

func NewError(errorType ErrorType, message string) *Error

func WrapError

func WrapError(cause error, errorType ErrorType, message string) *Error

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type ErrorType

type ErrorType string

ErrorType identifies the category of a rate limiter error.

const (
	ErrorTypeInternal     ErrorType = "internal_error"
	ErrorTypeRateLimit    ErrorType = "rate_limit_exceeded"
	ErrorTypeInvalidInput ErrorType = "invalid_input"
)

type FixedWindowStrategy

type FixedWindowStrategy struct {
	WindowSize  time.Duration
	MaxRequests int

	IdentifierLimits map[string]int
	ResourceLimits   map[string]int
}

FixedWindowStrategy implements fixed-window rate limiting.

func NewFixedWindowStrategy

func NewFixedWindowStrategy(windowSize time.Duration, maxRequests int) *FixedWindowStrategy

func (*FixedWindowStrategy) CalculateWindows

func (s *FixedWindowStrategy) CalculateWindows(now time.Time) []TimeWindow

func (*FixedWindowStrategy) GetLimit

func (s *FixedWindowStrategy) GetLimit(key RateLimitKey) int

func (*FixedWindowStrategy) SetIdentifierLimit

func (s *FixedWindowStrategy) SetIdentifierLimit(identifier string, limit int)

func (*FixedWindowStrategy) SetResourceLimit

func (s *FixedWindowStrategy) SetResourceLimit(resource string, limit int)

func (*FixedWindowStrategy) ShouldAllow

func (s *FixedWindowStrategy) ShouldAllow(counts map[string]int, limit int) bool

type Limit

type Limit struct {
	RequestsPerHour   int
	RequestsPerMinute int
	BurstCapacity     int
	CustomWindows     map[string]WindowLimit
}

Limit defines rate limits for a specific entity.

type LimitDecision

type LimitDecision struct {
	Allowed      bool
	CurrentCount int
	Limit        int
	ResetsAt     time.Time
	RetryAfter   *time.Duration
}

LimitDecision represents the result of a rate limit check.

type MultiWindowStrategy

type MultiWindowStrategy struct {
	Windows          []WindowConfig
	IdentifierLimits map[string][]WindowConfig
	ResourceLimits   map[string][]WindowConfig
}

MultiWindowStrategy enforces multiple limits simultaneously (for example: 100/min AND 1000/hour).

func NewMultiWindowStrategy

func NewMultiWindowStrategy(windows []WindowConfig) *MultiWindowStrategy

func (*MultiWindowStrategy) CalculateWindows

func (s *MultiWindowStrategy) CalculateWindows(now time.Time) []TimeWindow

func (*MultiWindowStrategy) GetLimit

func (s *MultiWindowStrategy) GetLimit(key RateLimitKey) int

func (*MultiWindowStrategy) ShouldAllow

func (s *MultiWindowStrategy) ShouldAllow(counts map[string]int, _ int) bool

type RateLimitEntry

type RateLimitEntry struct {
	PK string `theorydb:"pk" json:"pk"`
	SK string `theorydb:"sk" json:"sk"`

	Identifier string `json:"identifier"`
	Resource   string `json:"resource"`
	Operation  string `json:"operation"`

	WindowStart int64  `json:"window_start"`
	WindowType  string `json:"window_type"`
	WindowID    string `json:"window_id"`

	Count int64 `json:"count"`

	TTL int64 `theorydb:"ttl" json:"ttl"`

	CreatedAt time.Time         `theorydb:"created_at" json:"created_at"`
	UpdatedAt time.Time         `theorydb:"updated_at" json:"updated_at"`
	Metadata  map[string]string `json:"metadata,omitempty"`
}

RateLimitEntry tracks rate limit usage in DynamoDB.

Storage key shape:

  • PK: {identifier}#{window_start_unix}
  • SK: {resource}#{operation}

func (*RateLimitEntry) GetCompositeID

func (r *RateLimitEntry) GetCompositeID() string

func (*RateLimitEntry) SetKeys

func (r *RateLimitEntry) SetKeys()

func (*RateLimitEntry) SetTTL

func (r *RateLimitEntry) SetTTL(windowDuration time.Duration, bufferDuration time.Duration)

func (RateLimitEntry) TableName

func (RateLimitEntry) TableName() string

type RateLimitKey

type RateLimitKey struct {
	Identifier string
	Resource   string
	Operation  string
	Metadata   map[string]string
}

RateLimitKey identifies a unique rate limit bucket.

type RateLimitStrategy

type RateLimitStrategy interface {
	CalculateWindows(now time.Time) []TimeWindow
	GetLimit(key RateLimitKey) int
	ShouldAllow(counts map[string]int, limit int) bool
}

RateLimitStrategy defines how windows and limits are calculated.

type RateLimitWindow

type RateLimitWindow struct {
	WindowType string
	Start      time.Time
	End        time.Time
}

RateLimitWindow represents a time window for rate limiting.

func GetDayWindow

func GetDayWindow(now time.Time) RateLimitWindow

func GetFixedWindow

func GetFixedWindow(now time.Time, duration time.Duration) RateLimitWindow

func GetHourWindow

func GetHourWindow(now time.Time) RateLimitWindow

func GetMinuteWindow

func GetMinuteWindow(now time.Time) RateLimitWindow

type RateLimiter

type RateLimiter interface {
	// CheckLimit checks whether a request should be allowed under the current strategy.
	CheckLimit(ctx context.Context, key RateLimitKey) (*LimitDecision, error)

	// RecordRequest records a request occurrence (for non-atomic implementations).
	RecordRequest(ctx context.Context, key RateLimitKey) error

	// GetUsage returns current usage statistics for a key.
	GetUsage(ctx context.Context, key RateLimitKey) (*UsageStats, error)
}

RateLimiter defines the interface for rate limiting implementations.

type RealClock

type RealClock struct{}

RealClock implements Clock using actual time.

func (RealClock) Now

func (RealClock) Now() time.Time

type SlidingWindowStrategy

type SlidingWindowStrategy struct {
	WindowSize  time.Duration
	MaxRequests int
	Granularity time.Duration

	IdentifierLimits map[string]int
	ResourceLimits   map[string]int
}

SlidingWindowStrategy implements sliding-window rate limiting.

func NewSlidingWindowStrategy

func NewSlidingWindowStrategy(windowSize time.Duration, maxRequests int, granularity time.Duration) *SlidingWindowStrategy

func (*SlidingWindowStrategy) CalculateWindows

func (s *SlidingWindowStrategy) CalculateWindows(now time.Time) []TimeWindow

func (*SlidingWindowStrategy) GetLimit

func (s *SlidingWindowStrategy) GetLimit(key RateLimitKey) int

func (*SlidingWindowStrategy) SetIdentifierLimit

func (s *SlidingWindowStrategy) SetIdentifierLimit(identifier string, limit int)

func (*SlidingWindowStrategy) SetResourceLimit

func (s *SlidingWindowStrategy) SetResourceLimit(resource string, limit int)

func (*SlidingWindowStrategy) ShouldAllow

func (s *SlidingWindowStrategy) ShouldAllow(counts map[string]int, limit int) bool

type TimeWindow

type TimeWindow struct {
	Start time.Time
	End   time.Time
	Key   string
}

TimeWindow represents a time period for rate limiting.

type UsageStats

type UsageStats struct {
	Identifier    string
	Resource      string
	CurrentHour   UsageWindow
	CurrentMinute UsageWindow
	DailyTotal    int
	CustomWindows map[string]UsageWindow
}

UsageStats provides detailed usage information.

type UsageWindow

type UsageWindow struct {
	Count       int
	Limit       int
	WindowStart time.Time
	WindowEnd   time.Time
}

UsageWindow represents usage within a time window.

type WindowConfig

type WindowConfig struct {
	Duration    time.Duration
	MaxRequests int
}

type WindowLimit

type WindowLimit struct {
	Duration time.Duration
	Requests int
}

WindowLimit defines limits for a custom time window.

Directories

Path Synopsis
Package middleware provides HTTP middleware for the AppTheory limited rate limiter.
Package middleware provides HTTP middleware for the AppTheory limited rate limiter.

Jump to

Keyboard shortcuts

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