Exception: X::TooManyRequests

Inherits:
ClientError show all
Defined in:
x-core/lib/x/core/errors/too_many_requests.rb

Overview

Error raised when rate limit is exceeded (HTTP 429)

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from X::HTTPError

Instance Method Details

#exhausted_rate_limits ⇒ Array<RateLimit>

The rate limits with no requests left, one of which refused the request

Examples:

Name the windows that are used up

error.exhausted_rate_limits.map(&:type) # => ["app-limit-24hour"]

Returns:

  • (Array<RateLimit>) —

    the reported limits that are exhausted



37
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 37

def exhausted_rate_limits = rate_limits.select(&:exhausted?)

#limiting_rate_limit ⇒ RateLimit?

The exhausted rate limit that resets last, which a request waits for

Examples:

Name the window that refused the request

error.limiting_rate_limit&.type # => "app-limit-24hour"

Returns:

  • (RateLimit, nil) —

    the limit, or nil if the response reports none as exhausted



45
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 45

def limiting_rate_limit = exhausted_rate_limits.max_by(&:reset_at)

#rate_limit ⇒ RateLimit?

The 15-minute rate limit of the endpoint, which nearly every response reports

Examples:

Read how many of the 15-minute requests are left

error.rate_limit&.remaining # => 3

Returns:

  • (RateLimit, nil) —

    the rate limit, or nil if the response reports none



29
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 29

def rate_limit = rate_limits.find { |limit| limit.type.eql?(RateLimit::RATE_LIMIT_TYPE) }

#rate_limits ⇒ Array<RateLimit>

The rate limits the response reports in its headers, as X::Response reports them

They are read once and frozen, since the other readers of the error, and the wait before a request is sent again, read them too, so that a caller changing them changes none of those.

Examples:

Print how many requests remain in each window

error.rate_limits.each { |limit| puts "#{limit.type}: #{limit.remaining}" }

Returns:

  • (Array<RateLimit>) —

    the 15-minute limit, and the 24-hour app and user limits when reported, frozen



19
20
21
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 19

def rate_limits
  @rate_limits ||= RateLimit.__send__(:all_from, http_response).freeze
end

#reset_at ⇒ Time?

Get the time when the rate limit resets

Examples:

Get the reset time

error.reset_at

Returns:

  • (Time, nil) —

    the reset time, or nil if the response does not say when the limit resets



53
54
55
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 53

def reset_at
  limiting_rate_limit&.reset_at
end

#reset_in ⇒ Integer?

Get the seconds until the rate limit resets

Examples:

Get the time until reset

error.reset_in

Returns:

  • (Integer, nil) —

    the seconds until reset, or nil if the response does not say when the limit resets



63
64
65
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 63

def reset_in
  limiting_rate_limit&.reset_in
end

#retry_after ⇒ Integer?

The seconds to wait before retrying, as the response asks

A Retry-After header counts the seconds from when the response was sent, so it says the same thing however far this machine's clock is from the API's, where reset_in is off by the difference between the two. The header is preferred for that reason, and the limit that refused the request answers for a response that carries none. X recommends waiting a minute, doubling the wait for each retry after, when it says neither.

Examples:

Wait before retrying

sleep(error.retry_after || 60)

Returns:

  • (Integer, nil) —

    the seconds to wait before retrying, or nil if the response does not say



78
# File 'x-core/lib/x/core/errors/too_many_requests.rb', line 78

def retry_after = super || reset_in