cmd/pull: add retry to curl bottle download (#232)

Works around issue with GET and HEAD apparently acting differently, and
bottle downloads failing even after successful polling completion.
This commit is contained in:
Andrew Janke 2016-05-11 09:52:35 -07:00
parent 63ea9295cf
commit b5a44161a4

View File

@ -514,37 +514,57 @@ module Homebrew
next next
end end
# Poll for publication completion using a quick HEAD, to avoid spurious error messages # Poll for publication completion using a quick partial HEAD, to avoid spurious error messages
# 401 error is normal while file is still in async publishing process # 401 error is normal while file is still in async publishing process
url = URI(bottle_info.url) url = URI(bottle_info.url)
puts "Verifying bottle: #{File.basename(url.path)}" puts "Verifying bottle: #{File.basename(url.path)}"
http = Net::HTTP.new(url.host, url.port) http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true http.use_ssl = true
retry_count = 0
http.start do http.start do
while true do while true do
req = Net::HTTP::Head.new bottle_info.url req = Net::HTTP::Head.new bottle_info.url
res = http.request req res = http.request req
retry_count += 1
if res.is_a?(Net::HTTPSuccess) if res.is_a?(Net::HTTPSuccess)
break break
elsif res.is_a?(Net::HTTPClientError) elsif res.is_a?(Net::HTTPClientError)
if retry_count >= max_retries if retry_count >= max_retries
raise "Failed to download #{f} bottle from #{url}!" raise "Failed to find published #{f} bottle at #{url}!"
end end
print(wrote_dots ? "." : "Waiting on Bintray.") print(wrote_dots ? "." : "Waiting on Bintray.")
wrote_dots = true wrote_dots = true
sleep poll_retry_delay_seconds sleep poll_retry_delay_seconds
retry_count += 1
else else
raise "Failed to download #{f} bottle from #{url} (#{res.code} #{res.message})!" raise "Failed to find published #{f} bottle at #{url} (#{res.code} #{res.message})!"
end end
end end
end end
# Actual download and verification # Actual download and verification
# We do a retry on this, too, because sometimes the external curl will fail even
# when the prior HEAD has succeeded.
puts "\n" if wrote_dots puts "\n" if wrote_dots
filename = File.basename(url.path) filename = File.basename(url.path)
curl_retry_delay_seconds = 4
max_curl_retries = 1
retry_count = 0
# We're in the cache; make sure to force re-download # We're in the cache; make sure to force re-download
curl url, "-o", filename while true do
begin
retry_count
curl url, "-o", filename
break
rescue
if retry_count >= max_curl_retries
raise "Failed to download #{f} bottle from #{url}!"
end
puts "curl download failed; retrying in #{curl_retry_delay_seconds} sec"
sleep curl_retry_delay_seconds
curl_retry_delay_seconds *= 2
retry_count += 1
end
end
checksum = Checksum.new(:sha256, bottle_info.sha256) checksum = Checksum.new(:sha256, bottle_info.sha256)
Pathname.new(filename).verify_checksum(checksum) Pathname.new(filename).verify_checksum(checksum)
end end