Documentation
¶
Overview ¶
Example ¶
Example demonstrates basic usage of the token bucket rate limiter
package main
import (
"fmt"
"github.com/1mb-dev/goflow/pkg/ratelimit/bucket"
)
func main() {
// Create a rate limiter that allows 10 requests per second with a burst of 5
limiter, err := bucket.NewSafe(10, 5)
if err != nil {
panic(fmt.Sprintf("Failed to create limiter: %v", err))
}
// Check if a request is allowed (non-blocking)
if limiter.Allow() {
fmt.Println("Request allowed")
} else {
fmt.Println("Request denied")
}
}
Output: Request allowed
Example (Configuration) ¶
Example_configuration demonstrates advanced configuration
package main
import (
"fmt"
"time"
"github.com/1mb-dev/goflow/pkg/ratelimit/bucket"
)
func main() {
// Create with specific configuration
config := bucket.Config{
Rate: bucket.Every(100 * time.Millisecond), // 1 token every 100ms
Burst: 5,
InitialTokens: 2, // Start with 2 tokens instead of full burst
}
limiter, err := bucket.NewWithConfigSafe(config)
if err != nil {
panic(fmt.Sprintf("Failed to create limiter: %v", err))
}
fmt.Printf("Initial tokens: %.0f\n", limiter.Tokens())
fmt.Printf("Rate limit: %.1f/sec\n", limiter.Limit())
fmt.Printf("Burst capacity: %d\n", limiter.Burst())
}
Output: Initial tokens: 2 Rate limit: 10.0/sec Burst capacity: 5
Example (DynamicConfiguration) ¶
Example_dynamicConfiguration demonstrates changing limits at runtime
package main
import (
"fmt"
"github.com/1mb-dev/goflow/pkg/ratelimit/bucket"
)
func main() {
limiter, err := bucket.NewSafe(5, 10)
if err != nil {
panic(fmt.Sprintf("Failed to create limiter: %v", err))
}
fmt.Printf("Original rate: %.0f/sec, burst: %d\n", limiter.Limit(), limiter.Burst())
// Increase the rate limit during high traffic
limiter.SetLimit(20)
fmt.Printf("Updated rate: %.0f/sec, burst: %d\n", limiter.Limit(), limiter.Burst())
// Reduce burst size for stricter limiting
limiter.SetBurst(5)
fmt.Printf("Final rate: %.0f/sec, burst: %d\n", limiter.Limit(), limiter.Burst())
}
Output: Original rate: 5/sec, burst: 10 Updated rate: 20/sec, burst: 10 Final rate: 20/sec, burst: 5
Example (MultipleTokens) ¶
Example_multipleTokens demonstrates consuming multiple tokens at once
package main
import (
"fmt"
"github.com/1mb-dev/goflow/pkg/ratelimit/bucket"
)
func main() {
// Create a rate limiter (10 tokens per second, burst of 20)
limiter, err := bucket.NewSafe(10, 20)
if err != nil {
panic(fmt.Sprintf("Failed to create limiter: %v", err))
}
// Try to consume 5 tokens at once
if limiter.AllowN(5) {
fmt.Println("Bulk operation allowed (5 tokens)")
}
// Check remaining tokens
remaining := limiter.Tokens()
fmt.Printf("Tokens remaining: %.0f\n", remaining)
}
Output: Bulk operation allowed (5 tokens) Tokens remaining: 15
Example (Reservation) ¶
Example_reservation demonstrates the reservation pattern
package main
import (
"fmt"
"time"
"github.com/1mb-dev/goflow/pkg/ratelimit/bucket"
)
func main() {
// Create a rate limiter (2 requests per second, burst of 3)
limiter, err := bucket.NewSafe(2, 3)
if err != nil {
panic(fmt.Sprintf("Failed to create limiter: %v", err))
}
// Use all burst tokens
for i := 0; i < 3; i++ {
limiter.Allow()
}
// Make a reservation for the next request
reservation := limiter.Reserve()
if reservation.OK() {
delay := reservation.Delay()
fmt.Printf("Need to wait %v before next request\n", delay.Round(time.Millisecond))
// Cancel the reservation if we don't want to wait
reservation.Cancel()
fmt.Println("Reservation canceled")
}
}
Output: Need to wait 500ms before next request Reservation canceled
Example (Wait) ¶
Example_wait demonstrates blocking until tokens are available
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/1mb-dev/goflow/pkg/ratelimit/bucket"
)
func main() {
// Create a slow rate limiter (1 request per second, burst of 1)
limiter, err := bucket.NewSafe(1, 1)
if err != nil {
panic(fmt.Sprintf("Failed to create limiter: %v", err))
}
ctx := context.Background()
// First request succeeds immediately
if err := limiter.Wait(ctx); err != nil {
log.Fatal(err)
}
fmt.Println("First request processed")
// Second request would need to wait, but we'll use a timeout
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer cancel()
if err := limiter.Wait(ctx); err != nil {
fmt.Printf("Second request failed: %v\n", err)
}
}
Output: First request processed Second request failed: context deadline exceeded
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var Inf = Limit(math.Inf(1))
Inf is the infinite rate limit; it allows all events.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Rate is the number of tokens added per second.
Rate Limit
// Burst is the maximum number of tokens that can be stored.
Burst int
// Clock provides the current time. If nil, SystemClock is used.
Clock Clock
// InitialTokens is the number of tokens to start with.
// If negative, starts with full capacity.
InitialTokens int
}
Config holds configuration options for creating a new Limiter.
type Limit ¶
type Limit float64
Limit represents the maximum frequency of events per unit time. A zero Limit allows no events. Use Inf for unlimited rates.
type Limiter ¶
type Limiter interface {
// Allow reports whether an event may happen now. It does not block.
Allow() bool
// AllowN reports whether n events may happen now. It does not block.
AllowN(n int) bool
// Wait blocks until an event can happen. It returns an error
// if the context is canceled or the deadline is exceeded.
Wait(ctx context.Context) error
// WaitN blocks until n events can happen. It returns an error
// if the context is canceled or the deadline is exceeded.
WaitN(ctx context.Context, n int) error
// Reserve returns a Reservation that indicates how long the caller
// must wait before n events can happen.
Reserve() *Reservation
// ReserveN returns a Reservation that indicates how long the caller
// must wait before n events can happen.
ReserveN(n int) *Reservation
// SetLimit changes the rate limit. It preserves the current burst size.
SetLimit(limit Limit)
// SetBurst changes the burst size. It preserves the current rate limit.
SetBurst(burst int)
// Limit returns the current rate limit.
Limit() Limit
// Burst returns the current burst size.
Burst() int
// Tokens returns the number of tokens currently available.
Tokens() float64
}
Limiter controls how frequently events are allowed to happen using a token bucket algorithm. It supports burst traffic by maintaining a reservoir of tokens that can be consumed quickly.
func NewSafe ¶
NewSafe creates a new rate limiter with validation that returns an error instead of panicking. This is the recommended way to create rate limiters for production use.
func NewWithConfigSafe ¶
NewWithConfigSafe creates a new rate limiter with validation that returns an error instead of panicking. This is the recommended way to create rate limiters for production use.
type Reservation ¶
type Reservation struct {
// contains filtered or unexported fields
}
Reservation holds information about an event that should happen in the future. It can be used to cancel the reservation or check when the event should occur.
func (*Reservation) Cancel ¶
func (r *Reservation) Cancel()
Cancel cancels the reservation. This restores the tokens to the limiter if the reservation was valid.
func (*Reservation) Delay ¶
func (r *Reservation) Delay() time.Duration
Delay returns the time until the reservation should act. If the reservation is not OK, Delay returns zero.
func (*Reservation) DelayFrom ¶
func (r *Reservation) DelayFrom(now time.Time) time.Duration
DelayFrom returns the time until the reservation should act, measured from the given time.
func (*Reservation) OK ¶
func (r *Reservation) OK() bool
OK returns whether the reservation is valid.