Token Bucket Algorithm Implementation in Go
The token bucket algorithm is a widely used rate-limiting technique. It allows you to control the rate at which requests or operations can be processed, preventing overload and ensuring fairness. This challenge asks you to implement a token bucket in Go, enabling you to manage resource consumption effectively.
Problem Description
You are tasked with creating a TokenBucket struct in Go that implements the token bucket algorithm. The bucket should have a capacity (maximum number of tokens), a refill rate (tokens added per second), and a current token count. The TokenBucket should provide methods to:
NewTokenBucket(capacity int, refillRate float64): Constructor to initialize a new token bucket with the given capacity and refill rate.AllowRequest(amount int): Attempts to consumeamounttokens from the bucket. If sufficient tokens are available, the tokens are consumed, and the method returnstrue. If not enough tokens are available, the method returnsfalse.Refill(): Refills the bucket with tokens based on the refill rate and the elapsed time since the last refill. The refill should be proportional to the time passed. For simplicity, assume the time passed is always 1 second.GetTokensAvailable() int: Returns the number of tokens currently available in the bucket.
The bucket should automatically refill tokens at the specified rate. The refill rate is tokens per second. The AllowRequest method should check if there are enough tokens before consuming them.
Examples
Example 1:
Input: capacity = 10, refillRate = 2.0, amount = 5
Initial state: tokens = 10
AllowRequest(5)
Output: true
Explanation: The bucket has 10 tokens, which is enough to satisfy the request for 5 tokens. Tokens are consumed, leaving 5 tokens.
Example 2:
Input: capacity = 10, refillRate = 2.0, amount = 15
Initial state: tokens = 10
AllowRequest(15)
Output: false
Explanation: The bucket only has 10 tokens, which is not enough to satisfy the request for 15 tokens. The request is denied.
Example 3:
Input: capacity = 10, refillRate = 2.0
Initial state: tokens = 0
Refill()
Output: tokens = 2
Explanation: The bucket refills with 2 tokens (refillRate * 1 second).
Constraints
capacitymust be a positive integer.refillRatemust be a non-negative floating-point number.amountinAllowRequestmust be a non-negative integer.- The number of tokens in the bucket should never exceed
capacity. - The refill rate is tokens per second. Assume the time passed for refill is always 1 second.
- The implementation should be reasonably efficient. Avoid unnecessary allocations.
Notes
- Consider using a
sync.Mutexto protect the bucket's state if you plan to use it concurrently. For this challenge, you can assume single-threaded usage, so a mutex is not strictly required, but it's good practice to think about. - The refill logic should be straightforward: add
refillRatetokens to the bucket, but don't exceed thecapacity. - Think about how to handle the case where the request amount is zero.
- Focus on correctness and clarity of the code. Good variable names and comments are appreciated.
- The
GetTokensAvailable()method is primarily for testing and debugging purposes. It should return the current token count accurately.