limit

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2025 License: MIT Imports: 5 Imported by: 0

README

GO-LIMIT

This module provides different in-memory rate limiter implementations for Go.

They are all concurrency safe, but currently do not respect FIFO order.

Available Implementations

Limiter Description
Rolling Window (Sliding Log) The most accurate way to adhere to rate limits, uses more memory.
Token Bucket Uses the least memory, approximates the desired rate limit but might use slightly more during bursts.
Leaky Bucket Distributes incoming events into steady flow.

All implementations adhere to the same interface:

Method Description
Wait Blocks until allowed by the limiter. Does not return anything
WaitTimout Blocks until the limiter allows or the timeout expires. Returns an error only if timeout expires.
WaitContext Blocks until the limiter allows or the context is canceled. Returns an error only if the context was canceled.
Allowed Returns a boolean indicating if the operation is allowed by the limiter. It's non-blocking.
Reserve Blocks until a reservation is returned by the limiter. Returns a Reservation that has the desired TTL.
ReserveTimeout Blocks until a reservation is returned by the limiter or the timeout expires. Returns a Reservation that has the desired TTL or an error.
ReserveContext Blocks until a reservation is returned by the limiter or the context is canceled. Returns a Reservation that has the desired TTL or an error.
Clear Clears the limiter and returns to the initial state (does not wipe stat counters)
Stats Returns a struct with the current statistics of the limiter.

Reservations

Reservations provide a way to reserve capacity without immediately consuming it:

Method Description
Consume Consumes the reserved token. Returns error if already used/expired.
Cancel Cancels the reservation, returning the token to the pool.

Note: The leaky bucket implementation provides only basic reservation functionality, which doesn't align perfectly with the leaky bucket concept as it's primarily designed for rate smoothing rather than capacity reservation.

Reservations without TTL or not properly consumed or cancelled can lead to unused throughput or tokens being held indefinitely.

Example usage:


package main

import (
	"github.com/agustinbanchio/go-limit"
	"time"
)

func main() {

	limiter := limit.NewRollingWindow(1500, 1*time.Minute) // Don't allow more than 1500 requests in a 1-minute window.

	for i := 0; i < 1500; i++ {
		limiter.Wait()
	}
	// Those should be done almost instantly

	limiter.Wait() // This will block for almost a minute
}

Roadmap

Not much is planned for this module, but the following features are on the list:

  • ReservationGroups that allow reserving from multiple limiters at once with the same TTL.
  • Respect FIFO order for all implementations.
  • Immediate unblocking when a cancellation occurs.

Purpose and Alternatives

This module is intended to provide an easy-to-work with interface for common rate limiting needs. Contributions and suggestions are welcome, though implementation changes are not guaranteed.

If this interface or implementation doesn't meet your requirements, feel free to fork the project. Alternatively, consider these excellent rate limiting libraries for Go:

golang.org/x/time/rate - The extended standard library Go rate limiter uber-go/ratelimit - A leaky bucket rate limiter

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Limiter

type Limiter interface {
	// Wait blocks until the limiter allows the operation to proceed.
	Wait()
	// WaitTimeout blocks until the limiter allows the operation to proceed or the timeout expires.
	WaitTimeout(timeout time.Duration) error
	// WaitContext blocks until the limiter allows the operation to proceed or the context is done.
	WaitContext(ctx context.Context) error
	// Allowed returns true if the operation is allowed to proceed. It's non-blocking.
	Allowed() bool
	// Clear clears the limiter.
	Clear()
	// Stats returns the current stats of the limiter.
	Stats() Stats
	// Reserve blocks until the limiter can return a Reservation object. The Reservation has its own expiry duration or TTL. If nil it does not expire.
	Reserve(reservationTTL *time.Duration) Reservation
	// ReserveTimeout blocks until the limiter can return a Reservation object or the timeout expires. The Reservation has its own expiry duration or TTL. If nil it does not expire.
	ReserveTimeout(timeout time.Duration, reservationTTL *time.Duration) (Reservation, error)
	// ReserveContext requests a reservation with a context and returns a Reservation object.  The Reservation has its own expiry duration or TTL. If nil it does not expire. Context cancellation will only impact getting the reservation but will not expire the reservation itself.
	ReserveContext(ctx context.Context, reservationTTL *time.Duration) (Reservation, error)
}

Limiter is the interface that wraps the basic methods of a rate limiter. Limiters should be safe for concurrent use by multiple goroutines.

func NewLeakyBucket

func NewLeakyBucket(count int, duration time.Duration, maxQueue int) Limiter

func NewRollingWindow

func NewRollingWindow(count int, duration time.Duration) Limiter

NewRollingWindow creates a new rolling window rate limiter. The count parameter is the number of events allowed in the duration. The duration parameter is the time window in which the events are allowed.

func NewTokenBucket

func NewTokenBucket(count int, duration time.Duration) Limiter

type Reservation

type Reservation interface {
	// Consume uses the reservation, returning an error if the reservation expired
	Consume() error
	// Cancel releases the reservation without using it
	Cancel()
}

Reservation represents a reservation against a rate limiter that can be consumed or canceled

type Stats

type Stats struct {
	// The total number of requests allowed since the limiter was created. Doesn't get reset when the limiter is cleared.
	AllowedRequests int
	// The total number of requests denied since the limiter was created. This includes requests that were waiting but timed out.
	DeniedRequests int
	// The time when the next request will be allowed.
	NextAllowedTime time.Time
}

Stats represents the current statistics of a rate limiter.

Jump to

Keyboard shortcuts

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