diff --git a/app/services/tasks/dimensions_query_service.rb b/app/services/tasks/dimensions_query_service.rb index 0610f7e0a..2af050982 100644 --- a/app/services/tasks/dimensions_query_service.rb +++ b/app/services/tasks/dimensions_query_service.rb @@ -16,6 +16,8 @@ def query_dimensions(with_doi: true, page_size: 100) token = retrieve_token doi_clause = with_doi ? 'where doi is not empty' : 'where doi is empty' cursor = 0 + # Flag to track if retry has been attempted after token refresh + retry_attempted = false loop do begin @@ -47,11 +49,14 @@ def query_dimensions(with_doi: true, page_size: 100) cursor += page_size break if cursor >= total_count - elsif response.code == 403 + elsif response.code == 403 && !retry_attempted # If the token has expired, retrieve a new token and try the query again Rails.logger.warn('Received 403 Forbidden error. Retrying after token refresh.') token = retrieve_token redo + elsif response.code != 200 && retry_attempted + # If the token has expired and retry has already been attempted, raise a specific error + raise DimensionsPublicationQueryError, 'Retry attempted after token refresh failed with 403 Forbidden error' else raise DimensionsPublicationQueryError, "Failed to retrieve UNC affiliated articles from dimensions. Status code #{response.code}, response body: #{response.body}" end diff --git a/spec/services/tasks/dimensions_query_service_spec.rb b/spec/services/tasks/dimensions_query_service_spec.rb index fa926fecc..47e902161 100644 --- a/spec/services/tasks/dimensions_query_service_spec.rb +++ b/spec/services/tasks/dimensions_query_service_spec.rb @@ -72,6 +72,24 @@ expect(Rails.logger).to have_received(:error).with("HTTParty error during Dimensions API query: Failed to retrieve UNC affiliated articles from dimensions. Status code #{response_status}, response body: #{response_body}") end + # Checks that the function only retries once to prevent infinite loops + it 'raises and logs an error if the query returns a non 200 status code after a token refresh' do + allow(Rails.logger).to receive(:error) + allow(Rails.logger).to receive(:warn) + + unauthorized_status = 403 + server_error_status = 500 + stub_request(:post, 'https://app.dimensions.ai/api/dsl') + .to_return({status: unauthorized_status, body: 'Unauthorized'}, {status: server_error_status, body: 'Internal Server Error'}) + + expect { service.query_dimensions }.to raise_error(Tasks::DimensionsQueryService::DimensionsPublicationQueryError) + expect(WebMock).to have_requested(:post, 'https://app.dimensions.ai/api/auth').times(2) + expect(Rails.logger).to have_received(:warn).with('Received 403 Forbidden error. Retrying after token refresh.').once + + # Check if the error message has been logged + expect(Rails.logger).to have_received(:error).with("HTTParty error during Dimensions API query: Failed to retrieve UNC affiliated articles from dimensions. Status code #{server_error_status}, response body: Internal Server Error") + end + # Simulating token reretrieval and retry after expiration during query it 'refreshes the token and retries if query returns a 403' do allow(Rails.logger).to receive(:warn)