Skip to content

Commit

Permalink
Hyrax config option for solr http method (#5937)
Browse files Browse the repository at this point in the history
Add configuration option solr_default_method for use in specifying a default http method across blacklight and activefedora
  • Loading branch information
bbpennel authored Jan 25, 2023
1 parent 35340d5 commit e8edc51
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .dassie/app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def self.modified_field

# Because too many times on Samvera tech people raise a problem regarding a failed query to SOLR.
# Often, it's because they inadvertently exceeded the character limit of a GET request.
config.http_method = :post
config.http_method = Hyrax.config.solr_default_method

## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
config.default_solr_params = {
Expand Down
4 changes: 4 additions & 0 deletions .dassie/config/initializers/hyrax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
# Set the system-wide virus scanner
config.virus_scanner = Hyrax::VirusScanner

# The default method used for Solr queries. Values are :get or :post.
# Post is suggested to prevent issues with URL length.
config.solr_default_method = :post

##
# To index to the Valkyrie core, uncomment the following lines.
# config.query_index_from_valkyrie = true
Expand Down
2 changes: 1 addition & 1 deletion .koppie/app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def self.modified_field

# Because too many times on Samvera tech people raise a problem regarding a failed query to SOLR.
# Often, it's because they inadvertently exceeded the character limit of a GET request.
config.http_method = :post
config.http_method = Hyrax.config.solr_default_method

## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
config.default_solr_params = {
Expand Down
12 changes: 10 additions & 2 deletions app/services/hyrax/solr_query_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,29 @@ def self.document_model
end

##
# execute the query using a GET request
# @return [Hash] the results returned from solr for the current query
def get
solr_service.get(build)
end

##
# execute the solr query and return results
# @return [Hash] the results returned from solr for the current query
def query_result
solr_service.query_result(build)
end

##
# @return [Enumerable<SolrDocument>]
def solr_documents
get['response']['docs'].map { |doc| self.class.document_model.new(doc) }
query_result['response']['docs'].map { |doc| self.class.document_model.new(doc) }
end

##
# @return [Array<String>] ids of documents matching the current query
def get_ids # rubocop:disable Naming/AccessorMethodName
results = get
results = query_result
results['response']['docs'].map { |doc| doc['id'] }
end

Expand Down
38 changes: 22 additions & 16 deletions app/services/hyrax/solr_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def select_path
end

delegate :add, :commit, :count, :delete, :get, :instance, :ping, :post,
:query, :delete_by_query, :search_by_id, :wipe!, to: :new
:query, :query_result, :delete_by_query, :search_by_id, :wipe!, to: :new
end

# Wraps rsolr get
Expand Down Expand Up @@ -72,21 +72,27 @@ def post(query = nil, **args)
connection.post(solr_path, data: args)
end

# Wraps get by default
# Query solr using the provided or default http method, returning the result as a hash.
# @return [Hash] raw query result from solr
def query_result(query, **args)
Hyrax.logger.warn rows_warning unless args.key?(:rows)
# Use the provided solr query method, or fall back to the configured default
method = args.delete(:method) || Hyrax.config.solr_default_method

case method
when :get
get(query, **args)
when :post
post(query, **args)
else
raise "Unsupported HTTP method for querying SolrService (#{method.inspect})"
end
end

# Execute the provided query. Uses the configured http method by default.
# @return [Array<SolrHit>] the response docs wrapped in SolrHit objects
def query(query, **args)
Hyrax.logger.warn rows_warning unless args.key?(:rows)
method = args.delete(:method) || :get

result = case method
when :get
get(query, **args)
when :post
post(query, **args)
else
raise "Unsupported HTTP method for querying SolrService (#{method.inspect})"
end
result['response']['docs'].map do |doc|
query_result(query, **args)['response']['docs'].map do |doc|
::SolrHit.new(doc)
end
end
Expand Down Expand Up @@ -114,10 +120,10 @@ def add(solr_doc, commit: true)
end

# Wraps rsolr count
# @return [Hash] the hash straight form rsolr
# @return [Hash] the hash straight from rsolr
def count(query)
args = { rows: 0 }
get(query, **args)['response']['numFound'].to_i
query_result(query, **args)['response']['numFound'].to_i
end

# Wraps ActiveFedora::Base#search_by_id(id, opts)
Expand Down
2 changes: 1 addition & 1 deletion app/services/hyrax/workflow/status_list_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def search_solr
actionable_roles = roles_for_user
Hyrax.logger.debug("Actionable roles for #{@user.user_key} are #{actionable_roles}")
return [] if actionable_roles.empty?
WorkRelation.new.search_with_conditions(query(actionable_roles), method: :post)
WorkRelation.new.search_with_conditions(query(actionable_roles), method: Hyrax.config.solr_default_method)
end

def query(actionable_roles)
Expand Down
2 changes: 1 addition & 1 deletion lib/generators/hyrax/templates/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def self.modified_field

# Because too many times on Samvera tech people raise a problem regarding a failed query to SOLR.
# Often, it's because they inadvertently exceeded the character limit of a GET request.
config.http_method = :post
config.http_method = Hyrax.config.solr_default_method

## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
config.default_solr_params = {
Expand Down
5 changes: 5 additions & 0 deletions lib/hyrax/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,11 @@ def solr_select_path
@solr_select_path ||= ActiveFedora.solr_config.fetch(:select_path, 'select')
end

attr_writer :solr_default_method
def solr_default_method
@solr_default_method ||= :post
end

attr_writer :identifier_registrars
def identifier_registrars
@identifier_registrars ||= {}
Expand Down
19 changes: 12 additions & 7 deletions spec/services/hyrax/solr_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,16 @@
allow(described_class).to receive(:instance).and_return(double("instance", conn: mock_conn))
end

it "defaults to HTTP GET method" do
expect(mock_conn).to receive(:get).with('select', params: { rows: 2, q: 'querytext', qt: 'standard' }).and_return(stub_result)
it "defaults to HTTP POST method" do
expect(mock_conn).to receive(:post).with('select', data: { rows: 2, q: 'querytext', qt: 'standard' }).and_return(stub_result)
described_class.query('querytext', rows: 2)
end

it "allows callers to specify HTTP GET method" do
expect(mock_conn).to receive(:get).with('select', params: { rows: 2, q: 'querytext', qt: 'standard' }).and_return(stub_result)
described_class.query('querytext', rows: 2, method: :get)
end

it "allows callers to specify HTTP POST method" do
expect(mock_conn).to receive(:post).with('select', data: { rows: 2, q: 'querytext', qt: 'standard' }).and_return(stub_result)
described_class.query('querytext', rows: 2, method: :post)
Expand All @@ -109,14 +114,14 @@
end

it "wraps the solr response documents in Solr hits" do
expect(mock_conn).to receive(:get).with('select', params: { rows: 2, q: 'querytext', qt: 'standard' }).and_return(stub_result)
expect(mock_conn).to receive(:post).with('select', data: { rows: 2, q: 'querytext', qt: 'standard' }).and_return(stub_result)
result = described_class.query('querytext', rows: 2)
expect(result.size).to eq 1
expect(result.first.id).to eq 'x'
end

it "warns about not passing rows" do
allow(mock_conn).to receive(:get).and_return(stub_result)
allow(mock_conn).to receive(:post).and_return(stub_result)
expect(Hyrax.logger).to receive(:warn).with(/^Calling Hyrax::SolrService\.get without passing an explicit value for ':rows' is not recommended/)
described_class.query('querytext')
end
Expand All @@ -127,7 +132,7 @@
let(:doc) { { 'id' => 'valkyrie-x' } }

it "uses valkyrie solr based on config query_index_from_valkyrie" do
expect(mock_conn).to receive(:get).with('select', params: { q: 'querytext' }).and_return(stub_result)
expect(mock_conn).to receive(:post).with('select', data: { q: 'querytext' }).and_return(stub_result)

result = service.query('querytext')
expect(result.first.id).to eq 'valkyrie-x'
Expand Down Expand Up @@ -249,7 +254,7 @@
let(:stub_result) { { 'response' => { 'numFound' => '2' } } }

it "calls solr" do
expect(mock_conn).to receive(:get).with('select', params: { rows: 0, q: 'querytext', qt: 'standard' }).and_return(stub_result)
expect(mock_conn).to receive(:post).with('select', data: { rows: 0, q: 'querytext', qt: 'standard' }).and_return(stub_result)
allow(described_class).to receive(:instance).and_return(double("instance", conn: mock_conn))
expect(described_class.count('querytext')).to eq 2
end
Expand All @@ -258,7 +263,7 @@
subject(:service) { described_class.new(use_valkyrie: true) }

it "uses valkyrie solr based on config query_index_from_valkyrie" do
expect(mock_conn).to receive(:get).with('select', params: { rows: 0, q: 'querytext' }).and_return(stub_result)
expect(mock_conn).to receive(:post).with('select', data: { rows: 0, q: 'querytext' }).and_return(stub_result)
expect(service.count('querytext')).to eq 2
end
end
Expand Down

0 comments on commit e8edc51

Please sign in to comment.