lib/vagrant-skytap/api/client.rb in vagrant-skytap-0.3.1 vs lib/vagrant-skytap/api/client.rb in vagrant-skytap-0.3.2
- old
+ new
@@ -20,19 +20,21 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
require 'base64'
require "vagrant-skytap/version"
+require 'timeout'
module VagrantPlugins
module Skytap
module API
class Client
attr_reader :config, :http
+ DEFAULT_TIMEOUT = 120
MAX_RATE_LIMIT_RETRIES = 3
- DEFAULT_RETRY_AFTER_SECONDS = 10
+ DEFAULT_RETRY_AFTER_SECONDS = 5
def initialize(config)
@logger = Log4r::Logger.new("vagrant_skytap::api_client")
@config = config
@@ -81,38 +83,50 @@
if (query = [uri.query, extra_query].compact.join('&')).present?
path = [uri.path, query].join('?')
end
headers = default_headers.merge(options[:extra_headers] || {})
- tries = 0
retry_after = DEFAULT_RETRY_AFTER_SECONDS
+ most_recent_exception = nil
+
begin
- tries += 1
- http.send_request(method, URI.encode(path), body, headers).tap do |ret|
- @logger.debug("REST API response: #{ret.body}")
- unless ret.code =~ /^2\d\d/
- raise Errors::DoesNotExist, object_name: "Object '#{path}'" if ret.code == '404'
- error_class = case ret.code
- when '403'
- Errors::Unauthorized
- when '422'
- Errors::UnprocessableEntity
- when '423'
- Errors::ResourceBusy
- when '429'
- retry_after = ret['Retry-After'] || DEFAULT_RETRY_AFTER_SECONDS
- Errors::RateLimited
- else
- Errors::OperationFailed
+ Timeout.timeout(options[:timeout] || DEFAULT_TIMEOUT) do
+ begin
+ http.send_request(method, URI.encode(path), body, headers).tap do |ret|
+ @logger.debug("REST API response: #{ret.body}")
+ unless ret.code =~ /^2\d\d/
+ raise Errors::DoesNotExist, object_name: "Object '#{path}'" if ret.code == '404'
+ error_class = case ret.code
+ when '403'
+ Errors::Unauthorized
+ when '422'
+ Errors::UnprocessableEntity
+ when '423'
+ Errors::ResourceBusy
+ when '429'
+ retry_after = ret['Retry-After'] || DEFAULT_RETRY_AFTER_SECONDS
+ Errors::RateLimited
+ else
+ Errors::OperationFailed
+ end
+ raise error_class, err: error_string_from_body(ret)
+ end
end
- raise error_class, err: error_string_from_body(ret)
+ rescue Errors::RateLimited => ex
+ most_recent_exception = ex
+ @logger.info("Rate limited, wil retry in #{retry_after} seconds")
+ sleep retry_after.to_f + 0.1
+ retry
+ rescue Errors::ResourceBusy => ex
+ most_recent_exception = ex
+ @logger.debug("Resource busy, retrying")
+ sleep DEFAULT_RETRY_AFTER_SECONDS
+ retry
end
end
- rescue Errors::RateLimited => ex
- raise if tries > MAX_RATE_LIMIT_RETRIES
- @logger.info("Rate limited, wil retry in #{retry_after} seconds")
- sleep retry_after.to_f + 0.1
- retry
+ rescue Timeout::Error => ex
+ raise most_recent_exception if most_recent_exception
+ raise Errors::OperationFailed, "Timeout exceeded"
end
end
def error_string_from_body(resp)
resp = resp.body if resp.respond_to?(:body)