Class: RightScale::Downloader
Overview
Abstract download capabilities
Constant Summary collapse
- DEFAULT_MAX_DOWNLOAD_RETRIES =
10
Instance Attribute Summary collapse
-
#max_retry_period ⇒ Object
(Integer) Maximum retry period in seconds, only meaningful when using backoff algorithm.
-
#retry_period ⇒ Object
(Integer) Retry period in seconds.
-
#size ⇒ Object
readonly
(Integer) Size in bytes of last successful download (nil if none).
-
#speed ⇒ Object
readonly
(Integer) Speed in bytes/seconds of last successful download (nil if none).
-
#use_backoff ⇒ Object
(Boolean) Whether download should use a backoff algorithm to space retries.
Instance Method Summary collapse
-
#details ⇒ Object
Message summarizing last successful download details.
-
#download(url, dest, username = nil, password = nil, max_retries = DEFAULT_MAX_DOWNLOAD_RETRIES) ⇒ Object
Download file synchronously and report on success, download size and download speed.
-
#error ⇒ Object
Error message associated with last failure (nil if none).
-
#initialize(retry_period = 10, use_backoff = true, max_retry_period = 5 * 60) ⇒ Downloader
constructor
Initialize downloader with given retry period When using backoff algorithm the retry period specifies the initial value, the value then gets incremented after each retry exponentially until it reaches the specified maximum retry period.
-
#successful? ⇒ Boolean
Was last download successful?.
Constructor Details
#initialize(retry_period = 10, use_backoff = true, max_retry_period = 5 * 60) ⇒ Downloader
Initialize downloader with given retry period When using backoff algorithm the retry period specifies the initial value, the value then gets incremented after each retry exponentially until it reaches the specified maximum retry period
Parameters
- retry_period(Integer)
-
Retry period in seconds - defaults to 10 seconds
- use_backoff(Boolean)
-
Whether download should use a backoff algorithm to space retries - defaults to true
- max_retry_period(Integer)
-
Maximum retry period in seconds, only meaningful when using backoff algorithm - defaults to 5 minutes
41 42 43 44 45 46 47 |
# File 'lib/instance/downloader.rb', line 41 def initialize(retry_period = 10, use_backoff = true, max_retry_period = 5 * 60) @retry_period = retry_period @use_backoff = use_backoff @max_retry_period = max_retry_period if use_backoff platform = RightScale::Platform @found_curl = platform.filesystem.has_executable_in_path('curl') end |
Instance Attribute Details
#max_retry_period ⇒ Object
(Integer) Maximum retry period in seconds, only meaningful when using backoff algorithm
56 57 58 |
# File 'lib/instance/downloader.rb', line 56 def max_retry_period @max_retry_period end |
#retry_period ⇒ Object
(Integer) Retry period in seconds
50 51 52 |
# File 'lib/instance/downloader.rb', line 50 def retry_period @retry_period end |
#size ⇒ Object (readonly)
(Integer) Size in bytes of last successful download (nil if none)
59 60 61 |
# File 'lib/instance/downloader.rb', line 59 def size @size end |
#speed ⇒ Object (readonly)
(Integer) Speed in bytes/seconds of last successful download (nil if none)
62 63 64 |
# File 'lib/instance/downloader.rb', line 62 def speed @speed end |
#use_backoff ⇒ Object
(Boolean) Whether download should use a backoff algorithm to space retries
53 54 55 |
# File 'lib/instance/downloader.rb', line 53 def use_backoff @use_backoff end |
Instance Method Details
#details ⇒ Object
Message summarizing last successful download details
Return
- details(String)
-
Message with last url, download size and speed
154 155 156 |
# File 'lib/instance/downloader.rb', line 154 def details "Downloaded #{sanitize_uri(@last_url)} (#{ scale(size.to_i).join(' ') }) at #{ scale(speed.to_i).join(' ') }/s" end |
#download(url, dest, username = nil, password = nil, max_retries = DEFAULT_MAX_DOWNLOAD_RETRIES) ⇒ Object
Download file synchronously and report on success, download size and download speed. Use successful, size and speed to query about last download. If last download failed, use error to retrieve error message. Requires ‘curl’ to be available on PATH.
Parameters
- url(String)
-
URL to downloaded file
- dest(String)
-
Path where file should be saved on disk
- username(String)
-
Optional HTTP basic authentication username
- password(String)
-
Optional HTTP basic authentication password
- max_retries(Integer)
-
Maximum number of retries - defaults to DEFAULT_MAX_DOWNLOAD_RETRIES
Block
Call (optional) passed in block after each unsuccessful download attempt. Block must accept one argument corresponding to the last returned http code.
Return
- true
-
Download was successful
- false
-
Download failed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/instance/downloader.rb', line 101 def download(url, dest, username=nil, password=nil, max_retries=DEFAULT_MAX_DOWNLOAD_RETRIES) @errors = [] retry_count = error_code = 0 success = false reset_wait_time_span @errors << 'curl is not installed' unless @found_curl @errors << "destination file '#{dest}' is a directory" if File.directory?(dest) begin FileUtils.mkdir_p(File.dirname(dest)) unless File.directory?(File.dirname(dest)) rescue Exception => e @errors << e. end return false unless @errors.empty? # format curl command and redirect stderr away. # # note: ensure we use double-quotes (") to surround arguments on command # line because single-quotes (') are literals in windows. platform = RightScale::Platform user_opt = username && password ? "--user \"#{username}:#{password}\"" : "" dest = platform.filesystem.long_path_to_short_path(dest) cmd = "curl --fail --silent --show-error --insecure --location --connect-timeout 300 --max-time 3600 --write-out \"%{http_code} %{size_download} %{speed_download}\" #{user_opt} --output \"#{dest}\" \"#{url}\"" cmd = platform.shell.format_redirect_stderr(cmd) begin out = `#{cmd}` out = out.split success = $?.success? && out.size == 3 if success @size = out[1].to_i @speed = out[2].to_i @last_url = url return true else retry_count += 1 error_code = out[0].to_i yield error_code if block_given? sleep wait_time_span end end until success || retry_count >= max_retries unless success @errors << "#{retry_count} download attempts failed, last HTTP response code was #{error_code}" return false end true end |
#error ⇒ Object
Error message associated with last failure (nil if none)
Return
- error(String)
-
Error message
- nil
-
No error occured during last download
69 70 71 |
# File 'lib/instance/downloader.rb', line 69 def error error = (@errors.nil? || @errors.empty?) ? nil : @errors.join("\n") end |
#successful? ⇒ Boolean
Was last download successful?
Return
- true
-
If last download was successful or there was no download yet
- false
-
Otherwise
78 79 80 |
# File 'lib/instance/downloader.rb', line 78 def successful? error.nil? end |