rate

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2023 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

rate package contains abstraction over the rate-limiting concept which is a strategy for limiting mostly network traffic. It allows putting a cap on how often someone can repeat an action within a certain timeframe. The package does contain example alghoritm most often used in Web API's but there are much more algorithms already implemented in Go which are open-sourced by the Golang community. Use this package to abstract away the specific implementations provided by third party libraries. This requires to write an adapter for implementation to fulfill rate interfaces in your infrastructure layer.

Example
package main

import (
	"context"
	"time"

	"github.com/Prastiwar/Go-flow/rate"
	"github.com/Prastiwar/Go-flow/rate/memory"
	"github.com/Prastiwar/Go-flow/rate/slidingwindow"
)

func main() {
	sw, err := slidingwindow.NewAlgorithm(40, time.Minute, 20)
	if err != nil {
		panic(err)
	}

	store, err := memory.NewLimiterStore(context.Background(), sw, time.Hour)
	if err != nil {
		panic(err)
	}

	l, err := store.Limit(context.Background(), "{id}")
	if err != nil {
		panic(err)
	}

	t, err := l.Take(context.Background())
	if err != nil {
		panic(err)
	}

	if err := t.Use(); err != nil {
		panic(err)
	}

	if err := rate.Wait(context.Background(), t.ResetsAt()); err != nil {
		panic(err)
	}

	for i := 0; i < 15; i++ {
		if err := rate.ConsumeAndWait(context.Background(), l); err != nil {
			panic(err)
		}
	}
}

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrRateLimitExceeded is the error returned by Token.Use when the rate limit exceeds the limit.
	ErrRateLimitExceeded = errors.New("maximum rate limit exceeded")

	// ErrInvalidTokenValue is the error returned by Token.Use when Token is always falsy.
	ErrInvalidTokenValue = errors.New("token value exceeds limit")

	// ErrTokenCancelled is the error returned by Token.Use when CancellableToken.Cancel was used.
	ErrTokenCancelled = errors.New("token value exceeds limit")

	// MinTime is minimum time value.
	MinTime = time.Unix(-2208988800, 0)

	// MaxTime is maximum time value.
	MaxTime = MinTime.Add(1<<63 - 1)
)

Functions

func ConsumeAndWait

func ConsumeAndWait(ctx context.Context, l Limiter) error

ConsumeAndWait calls Take() on Limiter and immediately Use the Token. If ErrRateLimitExceeded error occurs it pauses the current goroutine until Limiter's ResetsAt() time deadline exceeds. If Take() returns any other error it'll immediately return this error. When ctx is canceled or ctx deadline exceeds before reset time it'll return this error.

func ConsumeNAndWait

func ConsumeNAndWait(ctx context.Context, l BurstLimiter, n uint64) error

ConsumeNAndWait is extended ConsumeAndWait() function that supports BurstLimiter.TakeN().

func Wait

func Wait(ctx context.Context, deadline time.Time) error

Wait pauses the current goroutine until deadline returning no error. If passed ctx is done before deadline - context's error is returned.

Types

type BurstLimiter

type BurstLimiter interface {
	Limiter

	// TakeN returns a new Token that allows to consume n tokens at once. This should not consume the token and not consider
	// the Token in availability calculation. Token should be reusable and time resistant and not usable only once it was got.
	// The context will be passed down to token which will use it if required for calculations.
	TakeN(ctx context.Context, n uint64) (Token, error)

	// Burst is the maximum number of tokens that can be consumed in a single call to TakeN, so higher Burst
	// value allow more events to happen at once. This is not the maximum available value to be consumed. Use Tokens
	// if you need such value.
	Burst() uint64
}

BurstLimiter extends Limiter functionality to accept burst, so it adds an additional limit to allow multiple events to be consumed at once.

type BurstReservationLimiter

type BurstReservationLimiter interface {
	BurstLimiter
	ReservationLimiter

	// ReserveN returns a new CancellableToken that allows to consume n tokens at once. This should not consume the token
	// but would potentially consider in availability calculation. CancellableToken should not be reusable and used for one-time only.
	// The context will be passed down to token which will use it if required for calculations.
	ReserveN(ctx context.Context, n uint64) (CancellableToken, error)
}

BurstLimiter extends BurstLimiter and ReservationLimiter functionality to accept burst reservation, so it allow to reserve multiple tokens at once with single composed token.

type CancellableToken

type CancellableToken interface {
	Token

	// Cancel frees up tokens to ReservationLimiter without actually consuming the token. Cancellation does not
	// allow to consume the token and Use function will return ErrTokenCancelled error.
	Cancel()
}

CancellableToken is a controlled token by ReservationLimiter. It extends the Token functionality with Cancel function that allows to free up the reserved tokens. In opposite to Token this should not be reusable and should be used one-time only for either consumption or cancellation. If token was canceled, Use function should return ErrTokenCancelled.

type Clock added in v0.11.0

type Clock interface {
	Now() time.Time
}

Clock is type which defines Now() to get actual time.Time value. Most of the time SystemClock can be used to fulfill the interface.

var (
	// SystemClock implements Clock interface and returns the current local time with time.Now().
	SystemClock Clock = &systemClock{}
)

type Limiter

type Limiter interface {
	// Take returns a new Token. This should not consume the token and not consider the Token in availability calculation.
	// Token should be reusable and time resistant and not usable only once it was got. The context will be passed down to
	// token which will use it if required for calculations.
	Take(ctx context.Context) (Token, error)

	// Tokens should return the remaining token amount that can be consumed at now time with Take, so higher
	// Tokens value allow more events to happen without a delay. A zero value means none token can be consumed now.
	Tokens(ctx context.Context) (uint64, error)

	// Limit should return the maximum amount of token that can be consumed within defined period with Take, so higher Limit
	// value allow more events to happen without a limit delay.
	Limit() uint64
}

Limiter controls how frequently events are allowed to happen. The implementation decides which algorithm should be used that can fulfill the interface. The Token name is syntactic and does not restrict implementation to use token/leaky bucket algorithms. The interface serves as a simple API to rate limiting and any other algorithms like a fixed window can be used.

type LimiterAlgorithm added in v0.11.0

type LimiterAlgorithm func() Limiter

LimiterAlgorithm is a function which returns new instance of Limiter using specific algorithm.

type LimiterStore

type LimiterStore interface {
	// Limit returns Limiter that was persisted before in store with corresponding key string.
	// If there was no entry found it should return default Limiter and persist it with specified key.
	Limit(ctx context.Context, key string) (Limiter, error)
}

LimiterStore is store for different Limiters indicated with key string.

type ReservationLimiter

type ReservationLimiter interface {
	Limiter

	// Reserve returns a new CancellableToken that allows to consume token. This should not consume the token
	// but would potentially consider in availability calculation. CancellableToken should not be reusable and used for one-time only.
	// The context will be passed down to token which will use it if required for calculations.
	Reserve(ctx context.Context) (CancellableToken, error)
}

ReservationLimiter extends Limiter functionality with reservations that are cancellable tokens so the caller can reserve a token which affects rate limiting calculation and decide later if he want to consume it or cancel and free up token allocation.

type Token

type Token interface {
	// Use consumes token and returns no error if succeeded. Returns ErrRateLimitExceeded when limit rate was exceeded.
	// If used with BurstLimiter it will not consume tokens below the limit before returning error. It will return ErrInvalidTokenValue
	// when Limit in BurstLimiter is lower than value provided in TakeN.
	Use() error

	// Allow reports whether an token can be consumed at this moment.
	Allow() bool

	// ResetsAt returns a time when token will be available to be consumed. At returned time Allow() should report true.
	ResetsAt() time.Time

	// Context returns the token's context. To change the context, use WithContext.
	// The returned context should be always non-nil; it defaults to the background context.
	// Since the token is controlled by Limiter, the context should be the value passed in Limiter.Take.
	// The token's context is immutable. To change it create a new Token using Limiter.Take.
	Context() context.Context
}

Token is a controlled token by Limiter. It allows the caller to consume it or check if it can be consumed and the actual time that it'll be allowed to be consumed.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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