rubyのhttp通信は,60秒でタイムアウトするように設定されている.通常はそれで問題ないのだけど,自前のスクリプトとかで時間のかかるモノを動かす場合に困る.
このタイムアウト時間はNet::HTTPのinitializeプロセスで60秒に設定されて,その後read_timeoutメソッドで変更可能になっている.
net/http.rb(Debian系なら/usr/lib/ruby/1.8/net/http.rb)を見ると下のような感じに書かれている.
# Creates a new Net::HTTP object for the specified +address+. # This method does not open the TCP connection. def initialize(address, port = nil) @address = address @port = (port || HTTP.default_port) @curr_http_version = HTTPVersion @seems_1_0_server = false @close_on_empty_response = false @socket = nil @started = false @open_timeout = nil @read_timeout = 60 @debug_output = nil @use_ssl = false @ssl_context = nil end ---中略--- # Seconds to wait until reading one block (by one read(2) call). # If the HTTP object cannot open a connection in this many seconds, # it raises a TimeoutError exception. attr_reader :read_timeout # Setter for the read_timeout attribute. def read_timeout=(sec) @socket.read_timeout = sec if @socket @read_timeout = sec end
この実装自体は自然なんだけれど,open-uriとかのラッピングされた状態で扱う場合にタイムアウトの変更ができなくて困る.どうしたらいいかと情報を探していたら,Net::HTTPを上書きしちゃう方法が照会されていた.
class Net::HTTP def initialize_new(address, port = nil) initialize_old(address, port) @read_timeout = 120 end alias :initialize_old :initialize alias :initialize :initialize_new end
かなり力ずくだけど確かに有効.