Skip to content

Latest commit

 

History

History
177 lines (144 loc) · 3.25 KB

README.md

File metadata and controls

177 lines (144 loc) · 3.25 KB

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)
	}
}