diff --git a/lib/ores_api.rb b/lib/ores_api.rb deleted file mode 100644 index 5b8e6c4e46..0000000000 --- a/lib/ores_api.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: true - -require_dependency "#{Rails.root}/lib/errors/api_error_handling" - -# Gets data from ORES — Objective Revision Evaluation Service -# https://meta.wikimedia.org/wiki/Objective_Revision_Evaluation_Service -class OresApi - include ApiErrorHandling - - # This is the maximum number of concurrent requests the app should make. - # As of 2018-09-19, ORES policy is a max of 4 parallel connections per IP: - # https://lists.wikimedia.org/pipermail/wikitech-l/2018-September/090835.html - # Use this if we need to make parallel threaded requests. - # CONCURRENCY = 4 - - ORES_SERVER_URL = 'https://ores.wikimedia.org' - REVS_PER_REQUEST = 50 - - # All the wikis with an articlequality model as of 2018-09-18 - # https://ores.wikimedia.org/v3/scores/ - AVAILABLE_WIKIPEDIAS = %w[en eu fa fr ru simple tr].freeze - - def self.valid_wiki?(wiki) - return true if wiki.project == 'wikidata' - wiki.project == 'wikipedia' && AVAILABLE_WIKIPEDIAS.include?(wiki.language) - end - - def initialize(wiki, update_service = nil) - raise InvalidProjectError unless OresApi.valid_wiki?(wiki) - @project_code = wiki.project == 'wikidata' ? 'wikidata' + 'wiki' : wiki.language + 'wiki' - @project_model = wiki.project == 'wikidata' ? 'itemquality' : 'articlequality' - @update_service = update_service - end - - def get_revision_data(rev_ids) - url_query = query_url(rev_ids) - response = ores_server.get(url_query) - response_body = response.body - ores_data = Oj.load(response_body) - ores_data - rescue StandardError => e - url = ORES_SERVER_URL + url_query - log_error(e, update_service: @update_service, - sentry_extra: { url:, response_body:, - project_code: @project_code, project_model: @project_model }) - return {} - end - - TYPICAL_ERRORS = [ - Errno::ETIMEDOUT, - Net::ReadTimeout, - Errno::ECONNREFUSED, - Oj::ParseError, - Errno::EHOSTUNREACH, - Faraday::ConnectionFailed, - Faraday::TimeoutError - ].freeze - - class InvalidProjectError < StandardError - end - - private - - def query_url(rev_ids) - base_url = "/v3/scores/#{@project_code}/?models=#{@project_model}&features&revids=" - url = base_url + rev_ids.join('|') - url - end - - def ores_server - conn = Faraday.new(url: ORES_SERVER_URL) - conn.headers['User-Agent'] = ENV['dashboard_url'] + ' ' + Rails.env - conn - end -end diff --git a/spec/lib/lift_wing_api_spec.rb b/spec/lib/lift_wing_api_spec.rb index 0b8a3e44bc..4aa8d387b6 100644 --- a/spec/lib/lift_wing_api_spec.rb +++ b/spec/lib/lift_wing_api_spec.rb @@ -2,27 +2,23 @@ require 'rails_helper' require "#{Rails.root}/lib/lift_wing_api" -require "#{Rails.root}/lib/ores_api" describe LiftWingApi do let(:rev_ids) { [641962088, 675892696] } - it 'returns the basically the same data as OresApi', vcr: true do - ores_output = OresApi.new(Wiki.first).get_revision_data rev_ids + it 'returns the basically the same data as ORES used to', vcr: true do lift_wing_output = described_class.new(Wiki.first).get_revision_data rev_ids digger = ['enwiki', 'scores', '641962088', 'articlequality', 'features', 'feature.english.stemmed.revision.stems_length'] - first_rev_ores = ores_output.dig(*digger) first_rev_liftwing = lift_wing_output.dig(*digger) - expect(first_rev_ores).to eq(first_rev_liftwing) + expect(first_rev_liftwing).to be_positive end it 'handles TextDeleted revs similarly', vcr: true do - ores_output = OresApi.new(Wiki.first).get_revision_data [708326238] lift_wing_output = described_class.new(Wiki.first).get_revision_data [708326238] # It doesn't need to have the exact same response, # but it does need the error type in the same place. digger = %w[enwiki scores 708326238 articlequality error type] - expect(ores_output.dig(*digger)).to eq(lift_wing_output.dig(*digger)) + expect(lift_wing_output.dig(*digger)).to include('TextDeleted') end end diff --git a/spec/lib/ores_api_spec.rb b/spec/lib/ores_api_spec.rb deleted file mode 100644 index c49c17a60f..0000000000 --- a/spec/lib/ores_api_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' -require "#{Rails.root}/lib/ores_api" - -describe OresApi do - context 'when the wiki is not a wikipedia or wikidata' do - before { stub_wiki_validation } - - let!(:wiki) { create(:wiki, project: 'wikivoyage', language: 'en') } - let(:subject) { described_class.new(wiki) } - - it 'raises an error' do - expect { subject }.to raise_error OresApi::InvalidProjectError - end - end - - describe '#get_revision_data' do - let(:rev_ids) { [641962088, 12345] } - let(:wiki) { create(:wiki, project: 'wikidata', language: 'en') } - - let(:subject) { described_class.new(Wiki.find(1)).get_revision_data(rev_ids) } - let(:subject2) { described_class.new(wiki).get_revision_data(rev_ids) } - - let(:first_id) { 641962088 } - let(:last_id) { first_id + OresApi::REVS_PER_REQUEST - 1 } - let(:many_rev_ids) { (first_id..last_id).to_a } - - it 'fetches json from ores.wikimedia.org for wikipedia' do - VCR.use_cassette 'ores_api' do - expect(subject).to be_a(Hash) - expect(subject.dig('enwiki', 'scores', '12345', 'articlequality', 'features')).to be_a(Hash) - expect(subject.dig('enwiki', 'scores', '641962088')).to be_a(Hash) - end - end - - it 'fetches json from ores.wikimedia.org for wikidata' do - VCR.use_cassette 'ores_api' do - expect(subject2).to be_a(Hash) - expect(subject2.dig('wikidatawiki', 'scores', '12345', 'itemquality', 'features')) - .to be_a(Hash) - expect(subject2.dig('wikidatawiki', 'scores', '641962088')).to be_a(Hash) - end - end - - it 'handles many revisions per request for wikipedia' do - VCR.use_cassette 'ores_api' do - result = described_class.new(Wiki.find(1)).get_revision_data(many_rev_ids) - expect(result.dig('enwiki', 'scores').count).to eq(OresApi::REVS_PER_REQUEST) - end - end - - it 'handles many revisions per request for wikidata' do - VCR.use_cassette 'ores_api' do - result = described_class.new(wiki).get_revision_data(many_rev_ids) - expect(result.dig('wikidatawiki', 'scores').count).to eq(OresApi::REVS_PER_REQUEST) - end - end - end - - describe 'error handling and calls ApiErrorHandling method' do - let(:rev_ids) { [641962088, 12345] } - let(:subject) do - described_class.new(Wiki.find(1)).get_revision_data(rev_ids) - end - - it 'handles timeout errors' do - stub_request(:any, %r{https://ores.wikimedia.org/.*}) - .to_raise(Errno::ETIMEDOUT) - expect_any_instance_of(described_class).to receive(:log_error).once - expect(subject).to be_empty - end - - it 'handles connection refused errors' do - stub_request(:any, %r{https://ores.wikimedia.org/.*}) - .to_raise(Faraday::ConnectionFailed) - expect_any_instance_of(described_class).to receive(:log_error).once - expect(subject).to be_empty - end - end -end