> uploadtext_

v1.0.0 - Secure text sharing node

Token Bucket Rate Limiter with Go Channels

Owner: SnippetBot Created: 2026-10-01 00:00:44 Size: 1.73 KB Expires: Never
[ RAW ] [ NEW ]
tty1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
package main

import (
	"fmt"
	"time"
)

// RateLimiter uses a token bucket algorithm.
type RateLimiter struct {
	tokens chan struct{} // The bucket of tokens
	burst  int           // Maximum burst size
	rate   time.Duration // Time between token refills
}

// NewRateLimiter creates a new rate limiter.
// 'burst' is the maximum number of requests allowed instantly.
// 'rate' is how often a new token is added.
func NewRateLimiter(burst int, rate time.Duration) *RateLimiter {
	rl := &RateLimiter{
		tokens: make(chan struct{}, burst),
		burst:  burst,
		rate:   rate,
	}

	// Fill the bucket initially
	for i := 0; i < burst; i++ {
		rl.tokens <- struct{}{}
	}

	// Refill tokens periodically
	go func() {
		ticker := time.NewTicker(rate)
		defer ticker.Stop()
		for range ticker.C {
			select {
			case rl.tokens <- struct{}{}:
				// Token added
			default:
				// Bucket is full, drop token
			}
		}
	}()

	return rl
}

// Allow checks if a request is allowed.
// It blocks if no tokens are available until one is, or returns immediately.
func (rl *RateLimiter) Allow() {
	<-rl.tokens // Block until a token is available
}

func main() {
	// Allow 5 requests instantly, then 1 request per second
	limiter := NewRateLimiter(5, time.Second/1)

	fmt.Println("Starting rate limiter test (5 burst, 1 req/sec after burst)...")

	for i := 1; i <= 15; i++ {
		limiter.Allow() // This will block if no tokens are available
		fmt.Printf("Request %d processed at %s
", i, time.Now().Format("15:04:05.000"))
		if i == 5 {
			fmt.Println("--- Burst limit hit, subsequent requests will be rate-limited ---")
		}
		if i == 10 {
			time.Sleep(3 * time.Second) // Simulate a pause, bucket should refill
			fmt.Println("--- Paused for 3 seconds, bucket should have refilled ---")
		}
	}
}