Add auto retry logic for auth expiry separate from normal failure retry

This commit is contained in:
Doug Henderson 2014-03-13 11:20:08 -07:00
parent bfa5225766
commit 2bed0748ab
3 changed files with 33 additions and 17 deletions

View File

@ -114,6 +114,8 @@ in the credentials. Detailed instructions on how to enable delegation for your d
The API client can automatically retry requests for recoverable errors. To enable retries, set the `client.retries` property to The API client can automatically retry requests for recoverable errors. To enable retries, set the `client.retries` property to
the number of additional attempts. To avoid flooding servers, retries invovle a 1 second delay that increases on each subsequent retry. the number of additional attempts. To avoid flooding servers, retries invovle a 1 second delay that increases on each subsequent retry.
In the case of authentication token expiry, the API client will attempt to refresh the token and retry the failed operation - this
is a specific exception to the retry rules.
The default value for retries is 0, but will be enabled by default in future releases. The default value for retries is 0, but will be enabled by default in future releases.

View File

@ -596,25 +596,34 @@ module Google
Retriable.retriable :tries => tries, Retriable.retriable :tries => tries,
:on => [TransmissionError], :on => [TransmissionError],
:on_retry => client_error_handler(request.authorization),
:interval => lambda {|attempts| (2 ** attempts) + rand} do :interval => lambda {|attempts| (2 ** attempts) + rand} do
result = request.send(connection, true) # This 2nd level retriable only catches auth errors, and supports 1 retry, which allows
# auth to be re-attempted without having to retry all sorts of other failures like
# NotFound, etc
Retriable.retriable :tries => 2,
:on => [AuthorizationError],
:on_retry => client_error_handler(request.authorization),
:interval => lambda {|attempts| (2 ** attempts) + rand} do
result = request.send(connection, true)
case result.status case result.status
when 200...300 when 200...300
result result
when 301, 302, 303, 307 when 301, 302, 303, 307
request = generate_request(request.to_hash.merge({ request = generate_request(request.to_hash.merge({
:uri => result.headers['location'], :uri => result.headers['location'],
:api_method => nil :api_method => nil
})) }))
raise RedirectError.new(result.headers['location'], result) raise RedirectError.new(result.headers['location'], result)
when 400...500 when 401
raise ClientError.new(result.error_message || "A client error has occurred", result) raise AuthorizationError.new(result.error_message || 'Invalid/Expired Authentication', result)
when 500...600 when 400, 402...500
raise ServerError.new(result.error_message || "A server error has occurred", result) raise ClientError.new(result.error_message || "A client error has occurred", result)
else when 500...600
raise TransmissionError.new(result.error_message || "A transmission error has occurred", result) raise ServerError.new(result.error_message || "A server error has occurred", result)
else
raise TransmissionError.new(result.error_message || "A transmission error has occurred", result)
end
end end
end end
end end

View File

@ -43,6 +43,11 @@ module Google
class ClientError < TransmissionError class ClientError < TransmissionError
end end
##
# A 401 HTTP error occurred.
class AuthorizationError < ClientError
end
## ##
# A 5xx class HTTP error occurred. # A 5xx class HTTP error occurred.
class ServerError < TransmissionError class ServerError < TransmissionError