ratelimiter

package module
v0.0.0-...-f088481 Latest Latest
Warning

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

Go to latest
Published: Mar 31, 2021 License: MIT Imports: 5 Imported by: 0

README

Go Reference Build Status Coverage Status Go Report Card

Rate Limiter

This package provides extensible rate limiter module in Go. There are 2 main extensible points:

  1. Rate limit algorithm (fixed window, sliding window, leaky bucket, etc.)
  2. Data store - to track request count by key (in-memory, Redis, Hazelcast, etc.)

Supported Algorithm

Fixed Window

This is the simplest algorithm for rate limiting. It divides the time into fixed window. For example a rate of 5 per 12 minutes gives us the following time windows:

  1. hh:00 - hh:11
  2. hh:12 - hh:23
  3. hh:24 - hh:35
  4. hh:36 - hh:47
  5. hh:48 - hh:59

Where hh is any hours in the clock. This algorithm is susceptible to spike near the window boundaries. For instance 5 requests at hh:11 and 5 requests at hh:12 are allowed because they happen to fall on 2 windows although if you see it without the windows, you are allowing 10 requests within 2 minutes.

Supported Data Store

In-memory

This is the simplest storage i.e. relying on in-mem data structure that is map to keep track of the request count. This is susceptible to data loss when the app restarts because the data is not persisted on disk.

How to use

go get github.com/yonasstephen/ratelimiter

Use it in your code

import github.com/yonasstephen/ratelimiter

func main() {
    repo := mocks.NewInMemRepository()
    clock := clock.Clock()
    // setting the limit to 5 per minute
    r := ratelimiter.NewFixedWindowRateLimiter("5", time.Minute, repo, clock)

    // increasing the rate limit count for user_123
    res, err := r.Allow(context.Background(), "user_123")
    if err != nil {
        fmt.Fatal("failed to check rate limit")
    }
    fmt.Println(res)
}

There exists an example on how to use the ratelimiter module as a HTTP middleware as well in the examples/httpserver folder.

What's next

These are future improvements that can be made on this module:

  • Thread-safe implementation of in-mem repository
  • Integration test for examples/httpserver
  • Sliding window algorithm implementation
  • Redis repository implementation

Contributing

Run tests

make test

If you make any changes to interface contract, you can run go generate to regenerate the mocks

make generate

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FixedWindowRateLimiter

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

FixedWindowRateLimiter is an implementation of RateLimiter interface with a fixed window algorithm

func NewFixedWindowRateLimiter

func NewFixedWindowRateLimiter(limit int, duration time.Duration, repo repository.Repository, clock clock.Clock) *FixedWindowRateLimiter

NewFixedWindowRateLimiter returns an instance of fixed window rate limiter. It takes limit & duration. The rate is defined as limit/duration. Example:

limit := 1
duration := 5*time.Second
// this gives us a rate of 1 request per 5 second window
rateLimiter := NewFixedWindowRateLimiter(limit, duration, repo, clock)

func (*FixedWindowRateLimiter) Allow

func (r *FixedWindowRateLimiter) Allow(ctx context.Context, key string) (*Result, error)

Allow increments the request rate of the given key for the current time window and returns the result

type RateLimiter

type RateLimiter interface {
	// Allow increments the rate of the request for a given key and returns
	// information about the result of the request.
	Allow(ctx context.Context, key string) (*Result, error)
}

RateLimiter is the interface of a rate limit module

type Result

type Result struct {
	// Allowed is the number of requests that are allowed at time.Now().
	// Zero value means that the request is not allowed i.e. has exceeded
	// the rate limit threshold
	Allowed int

	// Limit is the limit that was used to get this result
	Limit int

	// Remaining indicates how many remaining request is allowed at time.Now
	Remaining int

	// RetryAfer indicates the duration that requester need to wait
	// until the request will be allowed. If the request is allowed,
	// a zero value will be returned
	RetryAfter time.Duration

	// ResetAfter indicates the duration that the requester need to wait
	// until the time moves to the next rate limit window and hence resetting
	// the count. You can also think of this as the time when Limit == Remaining.
	ResetAfter time.Duration
}

Result embodies information about the current state of the rate limit

Directories

Path Synopsis
examples
httpserver command
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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