Skip to content

anboo/rate-limiter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rate Limiter

rate-limiter is a package for implementing a distributed rate limiter, supporting various storage backends such as Redis and PostgreSQL. It allows you to limit the frequency of operations using the "leaky bucket" algorithm.

Installation

Install the main package and the necessary adapters using go get:

go get github.com/anboo/rate-limiter
go get github.com/anboo/rate-limiter/redis
go get github.com/anboo/rate-limiter/postgresql

Usage

package main

import (
    "context"
    "github.com/anboo/rate-limiter"
)

var limit = ratelimiter.Limit{
    Key:   "example_key",
    Rate:  5,   // tokens per second
    Limit: 10,  // bucket size
}

In memory

Usage:

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/anboo/rate-limiter/in_memory"
)

func main() {
    ctx := context.Background()
    limiter := in_memory.NewInMemoryRateLimiter(10, time.Second)

    err := limiter.Wait(ctx)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    fmt.Println("Request allowed")
}

Redis adapter

Installation:

go get github.com/anboo/rate-limiter/redis

Usage:

package main

import (
    "context"
    "fmt"
    "github.com/anboo/rate-limiter"
    "github.com/anboo/rate-limiter/redis"
)

func main() {
    ctx := context.Background()
    redisClient := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })
    limiter := redis.NewLimiter(redisClient)

    result, err := limiter.Wait(ctx, limit)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    if result.NeedWait == 0 {
        fmt.Println("Request allowed")
    } else {
        fmt.Printf("Request denied. Please wait %s.\n", result.NeedWait)
    }
}

PostgreSQL adapter

Installation:

go get github.com/anboo/rate-limiter/postgresql

Usage:

package main

import (
    "context"
    "fmt"
    "github.com/anboo/rate-limiter"
    "github.com/anboo/rate-limiter/postgresql"
)

func main() {
	connStr := "user=username dbname=mydb sslmode=disable"
	db, err := sql.Open("postgres", connStr)
	if err != nil {
		log.Fatal(err)
	}
	
    ctx := context.Background()
    limiter := postgresql.NewLimiter(db)

    result, err := limiter.Wait(ctx, limit)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    if result.NeedWait == 0 {
        fmt.Println("Request allowed")
    } else {
        fmt.Printf("Request denied. Please wait %s.\n", result.NeedWait)
    }
}

Combine with in memory used as cache

Usage: Usage:

package main

import (
	"context"
	"fmt"
	"github.com/anboo/rate-limiter"
	"github.com/anboo/rate-limiter/in_memory"
	"github.com/anboo/rate-limiter/postgresql"
)

func main() {
	connStr := "user=username dbname=mydb sslmode=disable"
	db, err := sql.Open("postgres", connStr)
	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()
	limiter := rate_limiter.NewDecoratorLimiter(
		in_memory.NewInMemoryRateLimiter(),
		postgresql.NewLimiter(db),
	)

	result, err := limiter.Wait(ctx, limit)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if result.NeedWait == 0 {
		fmt.Println("Request allowed")
	} else {
		fmt.Printf("Request denied. Please wait %s.\n", result.NeedWait)
	}
}