From 9d833e37b32021479825a7beda54d41a6e23cc26 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Fri, 29 Oct 2021 00:13:29 +0200 Subject: [PATCH] Use Net::HTTP::Persistent for requests to Poseidon --- Gemfile | 1 + Gemfile.lock | 6 +++++- lib/runner/strategy/poseidon.rb | 21 +++++++++++---------- spec/lib/runner/strategy/poseidon_spec.rb | 13 ++++++------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index 960e1146..43aa0d60 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,7 @@ gem 'json_schemer' gem 'js-routes' gem 'kramdown' gem 'mimemagic' +gem 'net-http-persistent' gem 'nokogiri' gem 'pagedown-bootstrap-rails' gem 'pg' diff --git a/Gemfile.lock b/Gemfile.lock index ba6772b4..6432b7f6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -140,6 +140,7 @@ GEM chronic (0.10.2) coderay (1.1.3) concurrent-ruby (1.1.9) + connection_pool (2.2.5) crack (0.4.5) rexml crass (1.0.6) @@ -279,6 +280,8 @@ GEM multi_xml (0.6.0) multipart-post (2.1.1) nested_form (0.3.2) + net-http-persistent (4.0.0) + connection_pool (~> 2.2) netrc (0.11.0) newrelic_rpm (8.1.0) nio4r (2.5.8) @@ -574,6 +577,7 @@ DEPENDENCIES listen mimemagic mnemosyne-ruby + net-http-persistent newrelic_rpm nokogiri nyan-cat-formatter @@ -620,4 +624,4 @@ DEPENDENCIES whenever BUNDLED WITH - 2.2.23 + 2.2.29 diff --git a/lib/runner/strategy/poseidon.rb b/lib/runner/strategy/poseidon.rb index 88562759..781a4b2a 100644 --- a/lib/runner/strategy/poseidon.rb +++ b/lib/runner/strategy/poseidon.rb @@ -21,8 +21,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy def self.sync_environment(environment) url = "#{config[:url]}/execution-environments/#{environment.id}" - connection = Faraday.new nil, ssl: {ca_file: config[:ca_file]} - response = connection.put url, environment.to_json, headers + response = http_connection.put url, environment.to_json return true if [201, 204].include? response.status Rails.logger.warn("Could not create execution environment in Poseidon, got response: #{response.as_json}") @@ -39,8 +38,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy inactivityTimeout: config[:unused_runner_expiration_time].seconds, } Rails.logger.debug { "#{Time.zone.now.getutc.inspect}: Requesting new runner at #{url}" } - connection = Faraday.new nil, ssl: {ca_file: config[:ca_file]} - response = connection.post url, body.to_json, headers + response = http_connection.post url, body.to_json case response.status when 200 @@ -60,8 +58,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy def destroy_at_management Rails.logger.debug { "#{Time.zone.now.getutc.inspect}: Destroying runner at #{runner_url}" } - connection = Faraday.new nil, ssl: {ca_file: self.class.config[:ca_file]} - response = connection.delete runner_url, nil, self.class.headers + response = self.class.http_connection.delete runner_url self.class.handle_error response unless response.status == 204 rescue Faraday::Error => e raise Runner::Error::FaradayError.new("Request to Poseidon failed: #{e.inspect}") @@ -83,8 +80,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy # First, clean the workspace and second, copy all files to their location. # This ensures that no artefacts from a previous submission remain in the workspace. body = {copy: copy, delete: ['./']} - connection = Faraday.new nil, ssl: {ca_file: self.class.config[:ca_file]} - response = connection.patch url, body.to_json, self.class.headers + response = self.class.http_connection.patch url, body.to_json return if response.status == 204 Runner.destroy(@allocation_id) if response.status == 400 @@ -154,6 +150,12 @@ class Runner::Strategy::Poseidon < Runner::Strategy @headers ||= {'Content-Type' => 'application/json', 'Poseidon-Token' => config[:token]} end + def self.http_connection + @http_connection ||= Faraday.new(ssl: {ca_file: config[:ca_file]}, headers: headers) do |faraday| + faraday.adapter :net_http_persistent + end + end + def self.parse(response) JSON.parse(response.body).deep_symbolize_keys rescue JSON::ParserError => e @@ -167,8 +169,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy url = "#{runner_url}/execute" body = {command: command, timeLimit: @execution_environment.permitted_execution_time} Rails.logger.debug { "#{Time.zone.now.getutc.inspect}: Preparing command execution at #{url}: #{command}" } - connection = Faraday.new nil, ssl: {ca_file: self.class.config[:ca_file]} - response = connection.post url, body.to_json, self.class.headers + response = self.class.http_connection.post url, body.to_json case response.status when 200 diff --git a/spec/lib/runner/strategy/poseidon_spec.rb b/spec/lib/runner/strategy/poseidon_spec.rb index f81670da..cec90a31 100644 --- a/spec/lib/runner/strategy/poseidon_spec.rb +++ b/spec/lib/runner/strategy/poseidon_spec.rb @@ -109,7 +109,7 @@ describe Runner::Strategy::Poseidon do it 'raises an error' do faraday_connection = instance_double 'Faraday::Connection' - allow(Faraday).to receive(:new).and_return(faraday_connection) + allow(described_class).to receive(:http_connection).and_return(faraday_connection) %i[post patch delete].each {|message| allow(faraday_connection).to receive(message).and_raise(Faraday::TimeoutError) } expect { action.call }.to raise_error(Runner::Error::FaradayError) end @@ -122,20 +122,19 @@ describe Runner::Strategy::Poseidon do it 'makes the correct request to Poseidon' do faraday_connection = instance_double 'Faraday::Connection' - allow(Faraday).to receive(:new).and_return(faraday_connection) + allow(described_class).to receive(:http_connection).and_return(faraday_connection) allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status: 201)) action.call - expect(faraday_connection).to have_received(:put) do |url, body, headers| + expect(faraday_connection).to have_received(:put) do |url, body| expect(url).to match(%r{execution-environments/#{execution_environment.id}\z}) expect(body).to eq(execution_environment.to_json) - expect(headers).to include({'Content-Type' => 'application/json'}) end end shared_examples 'returns true when the api request was successful' do |status| it "returns true on status #{status}" do faraday_connection = instance_double 'Faraday::Connection' - allow(Faraday).to receive(:new).and_return(faraday_connection) + allow(described_class).to receive(:http_connection).and_return(faraday_connection) allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status: status)) expect(action.call).to be_truthy end @@ -144,7 +143,7 @@ describe Runner::Strategy::Poseidon do shared_examples 'returns false when the api request failed' do |status| it "returns false on status #{status}" do faraday_connection = instance_double 'Faraday::Connection' - allow(Faraday).to receive(:new).and_return(faraday_connection) + allow(described_class).to receive(:http_connection).and_return(faraday_connection) allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status: status)) expect(action.call).to be_falsey end @@ -160,7 +159,7 @@ describe Runner::Strategy::Poseidon do it 'returns false if Faraday raises an error' do faraday_connection = instance_double 'Faraday::Connection' - allow(Faraday).to receive(:new).and_return(faraday_connection) + allow(described_class).to receive(:http_connection).and_return(faraday_connection) allow(faraday_connection).to receive(:put).and_raise(Faraday::TimeoutError) expect(action.call).to be_falsey end