Class: Dratools::ExternalCommandRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/dratools/external_command_runner.rb

Overview

curl か wget を使って URL の確認とダウンロードを行うラッパー。

probe は短時間・無出力で済ませ、download は外部コマンドの進捗を端末へ流す。巨大ファイルを扱うため、download には総時間制限ではなく失速検知を使う。

Constant Summary collapse

CURL_COMMAND =
'curl'
WGET_COMMAND =
'wget'
SUPPORTED_COMMANDS =
[CURL_COMMAND, WGET_COMMAND].freeze
COMMAND_NOT_FOUND_MESSAGE =
'curl または wget が見つかりません'
DEFAULT_PROBE_TIMEOUT_SECONDS =
5
PROBE_BYTE_RANGE =
'0-0'
SINGLE_ATTEMPT_COUNT =
1
CURL_PROBE_OPTIONS =
['--location', '--fail', '--silent', '--show-error', '--range'].freeze
CURL_TIMEOUT_OPTION =
'--max-time'
CURL_CONNECT_TIMEOUT_OPTION =
'--connect-timeout'
CURL_SPEED_LIMIT_OPTION =
'--speed-limit'
CURL_SPEED_TIME_OPTION =
'--speed-time'
CURL_RETRY_OPTION =
'--retry'
CURL_OUTPUT_OPTION =
'--output'
CURL_DOWNLOAD_OPTIONS =
['--location', '--fail', '--continue-at', '-'].freeze
WGET_PROBE_OPTIONS =
['--spider'].freeze
WGET_TIMEOUT_OPTION =
'--timeout'
WGET_CONNECT_TIMEOUT_OPTION =
'--connect-timeout'
WGET_READ_TIMEOUT_OPTION =
'--read-timeout'
WGET_TRIES_OPTION =
'--tries'
WGET_WAITRETRY_OPTION =
'--waitretry'
WGET_CONTINUE_OPTION =
'--continue'
WGET_OUTPUT_OPTION =
'--output-document'

Instance Method Summary collapse

Constructor Details

#initialize(preferred: nil) ⇒ ExternalCommandRunner

Returns a new instance of ExternalCommandRunner.



42
43
44
# File 'lib/dratools/external_command_runner.rb', line 42

def initialize(preferred: nil)
  @preferred = preferred
end

Instance Method Details

#available_commandObject



46
47
48
49
# File 'lib/dratools/external_command_runner.rb', line 46

def available_command
  candidates = [@preferred, *SUPPORTED_COMMANDS].compact
  candidates.find { |command_name| executable_command?(command_name) }
end

#download_url(url, output_path) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/dratools/external_command_runner.rb', line 65

def download_url(url, output_path)
  tool = available_command || raise(CommandError, COMMAND_NOT_FOUND_MESSAGE)
  command =
    if File.basename(tool) == CURL_COMMAND
      [tool, *CURL_DOWNLOAD_OPTIONS,
       CURL_CONNECT_TIMEOUT_OPTION, Config.download_connect_timeout_seconds.to_s,
       CURL_SPEED_LIMIT_OPTION, Config.download_stall_speed_bytes_per_second.to_s,
       CURL_SPEED_TIME_OPTION, Config.download_stall_timeout_seconds.to_s,
       CURL_RETRY_OPTION, Config.download_retry_count.to_s,
       CURL_OUTPUT_OPTION, output_path, url]
    else
      [tool, WGET_CONTINUE_OPTION,
       "#{WGET_CONNECT_TIMEOUT_OPTION}=#{Config.download_connect_timeout_seconds}",
       "#{WGET_READ_TIMEOUT_OPTION}=#{Config.download_stall_timeout_seconds}",
       "#{WGET_TRIES_OPTION}=#{Config.download_retry_count}",
       "#{WGET_WAITRETRY_OPTION}=#{Config.download_retry_wait_seconds}",
       WGET_OUTPUT_OPTION, output_path, url]
    end
  run_streaming(command)
end

#probe_url(url, timeout: DEFAULT_PROBE_TIMEOUT_SECONDS) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/dratools/external_command_runner.rb', line 51

def probe_url(url, timeout: DEFAULT_PROBE_TIMEOUT_SECONDS)
  tool = available_command || raise(CommandError, COMMAND_NOT_FOUND_MESSAGE)
  # 巨大ファイルを落とさないよう、短時間・最小範囲の確認に留める。
  command =
    if File.basename(tool) == CURL_COMMAND
      [tool, *CURL_PROBE_OPTIONS, PROBE_BYTE_RANGE, CURL_TIMEOUT_OPTION, timeout.to_s,
       CURL_OUTPUT_OPTION, null_device, url]
    else
      [tool, *WGET_PROBE_OPTIONS, "#{WGET_TIMEOUT_OPTION}=#{timeout}",
       "#{WGET_TRIES_OPTION}=#{SINGLE_ATTEMPT_COUNT}", url]
    end
  run_quietly(command)
end