class RorVsWild::Client
def at_exit
def at_exit threads.each(&:join) end
def initialize(config)
def initialize(config) Kernel.at_exit(&method(:at_exit)) @api_url = config[:api_url] @api_key = config[:api_key] @timeout ||= config[:timeout] || DEFAULT_TIMEOUT @threads = Set.new @connections = [] @connection_count = 0 @mutex = Mutex.new @config = config @headers = { "Content-Type" => "application/json", "X-RorVsWild-Version" => RorVsWild::VERSION, "X-Ruby-Version" => RUBY_VERSION, } @headers["X-Rails-Version"] = Rails.version if defined?(Rails) @http_unauthorized = false end
def max_connections
def max_connections @max_connections ||= [Process.getrlimit(Process::RLIMIT_NOFILE).first / 10, 10].max end
def new_http
def new_http uri = URI(api_url) http = Net::HTTP.new(uri.host, uri.port) http.open_timeout = timeout http.keep_alive_timeout = 5 if uri.scheme == HTTPS # Disable peer verification while there is a memory leak with OpenSSL # http.verify_mode = OpenSSL::SSL::VERIFY_PEER # http.ca_file = CERTIFICATE_AUTHORITIES_PATH http.use_ssl = true end http end
def post(path, data)
def post(path, data) uri = URI(api_url + path) post = Net::HTTP::Post.new(uri.path, @headers) post.basic_auth(nil, api_key) post.body = data.to_json transmit(post) end
def post_async(path, data)
def post_async(path, data) Thread.new do begin threads.add(Thread.current) post(path, data) ensure threads.delete(Thread.current) end end end
def release_connection(http)
def release_connection(http) @mutex.synchronize { @connections.push(http) } if http end
def take_connection
def take_connection @mutex.synchronize { @connections.shift } end
def take_or_create_connection
def take_or_create_connection if http = take_connection http.start unless http.active? http elsif @connection_count < max_connections @connection_count += 1 new_http end end
def transmit(request)
def transmit(request) if !@http_unauthorized && http = take_or_create_connection response = http.request(request) @http_unauthorized = true if response.code == "401" response end rescue Exception => ex RorVsWild.logger.error(ex.full_message) ensure release_connection(http) end