Skip to content

Commit

Permalink
I35 valkyrize hyku wings (#2130)
Browse files Browse the repository at this point in the history
* 🚧 Get wings set up

This copies over the a modified wings initializer from AMS.  It also
runs the migrations for the Valkyrie engine.

```sh
bundle exec rails valkyrie_engine:install:migrations
bundle exec rails db:migrate
```

* 🚧 Adding temporary hack so we can proceed

The problem we're facing is that the Valkyrie::IndexingAdapter registers
the Valkyrie::Indexing::Solr::IndexingAdapter as the default adapter,
however, this does not work in a multi-tenant environment.  The 'core'
is set to 'hyrax-valkyrie' and it needs to be the tenant's ID.  Also the
connection url needs the username and password in it.

See:
  - https://github.com/samvera/hyrax/blob/double_combo/lib/valkyrie/indexing/solr/indexing_adapter.rb#L71
  - https://github.com/samvera/hyrax/blob/double_combo/lib/valkyrie/indexing/solr/indexing_adapter.rb#L86

We put in the hack to get us past this issue.

* 🧹 Multi-tenant connection & switching options

---------

Co-authored-by: LaRita Robinson <[email protected]>
  • Loading branch information
Kirk Wang and LaRita Robinson authored Jan 5, 2024
1 parent feafeac commit 6021bdd
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ GIT

GIT
remote: https://github.com/samvera/hyrax.git
revision: b7891b758411c59f71ff54212e0d250fcc47e35f
revision: c62e2b6431646151b954e1b23a02d4d3b78c7967
branch: double_combo
specs:
hyrax (5.0.0.rc2)
Expand Down
7 changes: 4 additions & 3 deletions app/models/solr_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def connection
# @return [Hash] options for the RSolr connection.
def connection_options
bl_defaults = Blacklight.connection_config
af_defaults = ActiveFedora::SolrService.instance.conn.options
af_defaults = Hyrax::SolrService.instance.conn.options
switchable_options.reverse_merge(bl_defaults).reverse_merge(af_defaults)
end

Expand All @@ -22,7 +22,8 @@ def ping
end

def switch!
ActiveFedora::SolrService.instance.conn = connection
Hyrax::SolrService.instance.conn = connection
Valkyrie::IndexingAdapter.adapters[:solr_index].connection = connection
Blacklight.connection_config = connection_options
Blacklight.default_index = nil
end
Expand All @@ -42,7 +43,7 @@ def remove!
end

def self.reset!
ActiveFedora::SolrService.reset!
Hyrax::SolrService.reset!
Blacklight.connection_config = Blacklight.blacklight_yml[::Rails.env].symbolize_keys
Blacklight.default_index = nil
end
Expand Down
33 changes: 33 additions & 0 deletions app/services/hyrax/custom_queries/find_by_bulkrax_identifier.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true
module Hyrax
module CustomQueries
##
# @see https://github.com/samvera/valkyrie/wiki/Queries#custom-queries
class FindByBulkraxIdentifier
def self.queries
[:find_by_bulkrax_identifier]
end

def initialize(query_service:)
@query_service = query_service
end

attr_reader :query_service
delegate :resource_factory, to: :query_service
delegate :orm_class, to: :resource_factory

##
# @param identifier String
def find_by_bulkrax_identifier(identifier:)
query_service.run_query(sql_by_bulkrax_identifier, identifier).first
end

def sql_by_bulkrax_identifier
<<-SQL
SELECT * FROM orm_resources
WHERE metadata -> 'bulkrax_identifier' ->> 0 = ?;
SQL
end
end
end
end
29 changes: 29 additions & 0 deletions app/services/wings/custom_queries/find_by_bulkrax_identifier.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true
module Wings
module CustomQueries
class FindByBulkraxIdentifier
# Custom query override specific to Wings
# Use:
# Hyrax.custom_queries.find_bulkrax_id(identifier: identifier, models: [ModelClass])

def self.queries
[:find_by_bulkrax_identifier]
end

attr_reader :query_service
delegate :resource_factory, to: :query_service

def initialize(query_service:)
@query_service = query_service
end

def find_by_bulkrax_identifier(identifier:, use_valkyrie: true)
af_object = ActiveFedora::Base.where("bulkrax_identifier_sim:#{identifier}").first

return af_object unless use_valkyrie

resource_factory.to_resource(object: af_object)
end
end
end
end
93 changes: 93 additions & 0 deletions config/initializers/wings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# frozen_string_literal: true
# rubocop:disable Metrics/BlockLength
Rails.application.config.after_initialize do
[
GenericWork,
Image
].each do |klass|
Wings::ModelRegistry.register("#{klass}Resource".constantize, klass)
# we register itself so we can pre-translate the class in Freyja instead of having to translate in each query_service
Wings::ModelRegistry.register(klass, klass)
end
Wings::ModelRegistry.register(Collection, Collection)
Wings::ModelRegistry.register(Hyrax::PcdmCollection, Collection)
Wings::ModelRegistry.register(Hyrax::AdministrativeSet, AdminSet)
Wings::ModelRegistry.register(AdminSet, AdminSet)

Valkyrie::MetadataAdapter.register(
Freyja::MetadataAdapter.new,
:freyja
)
Valkyrie.config.metadata_adapter = :freyja
Hyrax.config.query_index_from_valkyrie = true
Hyrax.config.index_adapter = :solr_index

Valkyrie::StorageAdapter.register(
Valkyrie::Storage::Disk.new(base_path: Rails.root.join("storage", "files"),
file_mover: FileUtils.method(:cp)),
:disk
)
Valkyrie.config.storage_adapter = :disk
Valkyrie.config.indexing_adapter = :solr_index

# load all the sql based custom queries
[
Hyrax::CustomQueries::Navigators::CollectionMembers,
Hyrax::CustomQueries::Navigators::ChildCollectionsNavigator,
Hyrax::CustomQueries::Navigators::ParentCollectionsNavigator,
Hyrax::CustomQueries::Navigators::ChildFileSetsNavigator,
Hyrax::CustomQueries::Navigators::ChildWorksNavigator,
Hyrax::CustomQueries::Navigators::FindFiles,
Hyrax::CustomQueries::FindAccessControl,
Hyrax::CustomQueries::FindCollectionsByType,
Hyrax::CustomQueries::FindFileMetadata,
Hyrax::CustomQueries::FindIdsByModel,
Hyrax::CustomQueries::FindManyByAlternateIds,
Hyrax::CustomQueries::FindModelsByAccess,
Hyrax::CustomQueries::FindCountBy,
Hyrax::CustomQueries::FindByDateRange,
Hyrax::CustomQueries::FindByBulkraxIdentifier
].each do |handler|
Hyrax.query_service.services[0].custom_queries.register_query_handler(handler)
end

[
Wings::CustomQueries::FindByBulkraxIdentifier
].each do |handler|
Hyrax.query_service.services[1].custom_queries.register_query_handler(handler)
end

Wings::ModelRegistry.register(GenericWorkResource, GenericWork)
Wings::ModelRegistry.register(ImageResource, Image)
end
# rubocop:enable Metrics/BlockLength

Rails.application.config.to_prepare do
Hyrax::AdministrativeSet.class_eval do
attribute :internal_resource, Valkyrie::Types::Any.default("AdminSet"), internal: true
end

Hyrax::PcdmCollection.class_eval do
attribute :internal_resource, Valkyrie::Types::Any.default("Collection"), internal: true
end

Hyrax::FileSet.class_eval do
attribute :internal_resource, Valkyrie::Types::Any.default("FileSet"), internal: true
end

Valkyrie.config.resource_class_resolver = lambda do |resource_klass_name|
klass_name = resource_klass_name.gsub(/Resource$/, '')
if %w[
GenericWork
Image
].include?(klass_name)
"#{klass_name}Resource".constantize
elsif 'Collection' == klass_name
Hyrax::PcdmCollection
elsif 'AdminSet' == klass_name
Hyrax::AdministrativeSet
else
klass_name.constantize
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20160111215816)
class EnableUuidExtension < ActiveRecord::Migration[5.0]
def change
enable_extension 'uuid-ossp'
end
end
19 changes: 19 additions & 0 deletions db/migrate/20240104192408_create_orm_resources.valkyrie_engine.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20161007101725)
class CreateOrmResources < ActiveRecord::Migration[5.0]
def options
if ENV["VALKYRIE_ID_TYPE"] == "string"
{ id: :text, default: -> { '(uuid_generate_v4())::text' } }
else
{ id: :uuid }
end
end

def change
create_table :orm_resources, **options do |t|
t.jsonb :metadata, null: false, default: {}
t.timestamps
end
add_index :orm_resources, :metadata, using: :gin
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20170124135846)
class AddModelTypeToOrmResources < ActiveRecord::Migration[5.0]
def change
add_column :orm_resources, :resource_type, :string
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20170531004548)
class ChangeModelTypeToInternalModel < ActiveRecord::Migration[5.1]
def change
rename_column :orm_resources, :resource_type, :internal_resource
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20171011224121)
class CreatePathGinIndex < ActiveRecord::Migration[5.1]
def change
add_index :orm_resources, 'metadata jsonb_path_ops', using: :gin
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20171204224121)
class CreateInternalResourceIndex < ActiveRecord::Migration[5.1]
def change
add_index :orm_resources, :internal_resource
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20180212092225)
class CreateUpdatedAtIndex < ActiveRecord::Migration[5.1]
def change
add_index :orm_resources, :updated_at
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
# This migration comes from valkyrie_engine (originally 20180802220739)
class AddOptimisticLockingToOrmResources < ActiveRecord::Migration[5.1]
def change
add_column :orm_resources, :lock_version, :integer
end
end
14 changes: 13 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2023_12_15_215708) do
ActiveRecord::Schema.define(version: 2024_01_04_192414) do

# These are extensions that must be enabled in order to support this database
enable_extension "hstore"
Expand Down Expand Up @@ -538,6 +538,18 @@
t.index ["namespace"], name: "index_minter_states_on_namespace", unique: true
end

create_table "orm_resources", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t|
t.jsonb "metadata", default: {}, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "internal_resource"
t.integer "lock_version"
t.index ["internal_resource"], name: "index_orm_resources_on_internal_resource"
t.index ["metadata"], name: "index_orm_resources_on_metadata", using: :gin
t.index ["metadata"], name: "index_orm_resources_on_metadata_jsonb_path_ops", opclass: :jsonb_path_ops, using: :gin
t.index ["updated_at"], name: "index_orm_resources_on_updated_at"
end

create_table "permission_template_accesses", id: :serial, force: :cascade do |t|
t.integer "permission_template_id"
t.string "agent_type"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

# OVERRIDE: class ActiveFedora::SolrService from Fedora v14.0.1
module ActiveFedora
# OVERRIDE: class Hyrax::SolrService from Hyrax 5.0
module Hyrax
module SolrServiceDecorator
# Get the count of records that match the query
# @param [String] query a solr query
Expand All @@ -11,10 +11,16 @@ module SolrServiceDecorator
#
# OVERRIDE: use `post` rather than `get` to handle larger query sizes
def count(query, args = {})
args = args.merge(rows: 0)
SolrService.post(query, args)['response']['numFound'].to_i
args = args.merge({ rows: 0, method: :post })
query_result(query, **args)['response']['numFound'].to_i
end

# TODO: does Valkyrie Solr Service need to be reset in some way?
def reset!
@old_service.reset! if @old_service
valkyrie_index.connection = valkyrie_index.default_connection
end
end
end

ActiveFedora::SolrService.singleton_class.send(:prepend, ActiveFedora::SolrServiceDecorator)
Hyrax::SolrService.singleton_class.send(:prepend, Hyrax::SolrServiceDecorator)

0 comments on commit 6021bdd

Please sign in to comment.