Time-based token bucket rate limiter

Crystal
class TokenBucket
  def initialize(@rate : Float64, @burst : Float64)
    @tokens = @burst
    @last = Time.monotonic
  end

  def allow?(cost : Float64 = 1.0) : Bool
    now = Time.monotonic
    @tokens = Math.min(@burst, @tokens + (now - @last).total_seconds * @rate)
    @last = now
    return false if @tokens < cost
    @tokens -= cost
    true
  end
end