From 9652f270a7bb4c7382e059c017c84af4820aaa0d Mon Sep 17 00:00:00 2001 From: Jeremy Friesen Date: Wed, 17 Jan 2024 10:25:28 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=81=20Add=20`Bulkrax.persistence=5Fada?= =?UTF-8?q?pter`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At present we have not incorporated using the `Bulkrax.persistence_adapter` into the application. It is instead put forward for discussion and review. Why introduce the adapter strategy? Because there are several instances of Bulkrax that are installed along various points of Hyrax versions as well as non-Hyrax versions; which means that there are some cases where we'll be using ActiveFedora and some where we'll be moving towards Valkyrie. The goal of the adapter is two fold: - Clarify and define the data interface between Bulkrax and the Main App - Allow for ease of maintaining Bulkrax releative to varying versions of Hyrax and Hyku; thus allowing folks to upgrade to new features of Bulkrax without mandating an upgrade of their entire persistence strategy. Related to: - https://github.com/scientist-softserv/hykuup_knapsack/issues/35 --- lib/bulkrax.rb | 32 ++++++++++++++++ lib/bulkrax/engine.rb | 6 +++ lib/bulkrax/persistence_layer.rb | 38 +++++++++++++++++++ .../active_fedora_adapter.rb | 27 +++++++++++++ .../persistence_layer/valkyrie_adapter.rb | 8 ++++ spec/lib/bulkrax_spec.rb | 8 ++++ 6 files changed, 119 insertions(+) create mode 100644 lib/bulkrax/persistence_layer.rb create mode 100644 lib/bulkrax/persistence_layer/active_fedora_adapter.rb create mode 100644 lib/bulkrax/persistence_layer/valkyrie_adapter.rb diff --git a/lib/bulkrax.rb b/lib/bulkrax.rb index 486a92292..3ca099995 100644 --- a/lib/bulkrax.rb +++ b/lib/bulkrax.rb @@ -35,6 +35,36 @@ class Configuration :reserved_properties, :server_name + attr_writer :persistence_adapter + + ## + # Configure the persistence adapter used for persisting imported data. + # + # @return [Bulkrax::PersistenceLayer::AbstractAdapter] + # @see Bulkrax::PersistenceLayer + def persistence_adapter + @persistence_adapter || derived_persistence_adapter + end + + def derived_persistence_adapter + if defined?(Hyrax) + # There's probably some configuration of Hyrax we could use to better refine this; but it's + # likely a reasonable guess. The main goal is to not break existing implementations and + # maintain an upgrade path. + if Gem::Version.new(Hyrax::VERSION) >= Gem::Version.new('6.0.0') + Bulkrax::PersistenceLayer::ValkyrieAdapter + else + Bulkrax::PersistenceLayer::ActiveFedoraAdapter + end + elsif defined?(ActiveFedora) + Bulkrax::PersistenceLayer::ActiveFedoraAdapter + elsif defined?(Valkyrie) + Bulkrax::PersistenceLayer::ValkyrieAdapter + else + raise "Unable to derive a persistence adapter" + end + end + attr_writer :use_locking def use_locking @@ -81,6 +111,8 @@ def config :object_factory=, :parsers, :parsers=, + :persistence_adapter, + :persistence_adapter=, :qa_controlled_properties, :qa_controlled_properties=, :related_children_field_mapping, diff --git a/lib/bulkrax/engine.rb b/lib/bulkrax/engine.rb index c48313c5b..063afddb5 100644 --- a/lib/bulkrax/engine.rb +++ b/lib/bulkrax/engine.rb @@ -13,6 +13,12 @@ class Engine < ::Rails::Engine end end + initializer 'requires' do + require 'bulkrax/persistence_layer' + require 'bulkrax/persistence_layer/active_fedora_adapter' if defined?(ActiveFedora) + require 'bulkrax/persistence_layer/valkyrie_adapter' if defined?(Valkyrie) + end + config.generators do |g| g.test_framework :rspec begin diff --git a/lib/bulkrax/persistence_layer.rb b/lib/bulkrax/persistence_layer.rb new file mode 100644 index 000000000..361e72e42 --- /dev/null +++ b/lib/bulkrax/persistence_layer.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Bulkrax + ## + # The target data layer where we write and read our imported {Bulkrax::Entry} objects. + module PersistenceLayer + # We're inheriting from an ActiveRecord exception as that is something we know will be here; and + # something that the main_app will be expect to be able to handle. + class ObjectNotFoundError < ActiveRecord::RecordNotFound + end + + # We're inheriting from an ActiveRecord exception as that is something we know will be here; and + # something that the main_app will be expect to be able to handle. + class RecordInvalid < ActiveRecord::RecordInvalid + end + + class AbstractAdapter + # @see ActiveFedora::Base.find + def self.find(id) + raise NotImplementedError, "#{self}.#{__method__}" + end + + def self.solr_name(field_name) + raise NotImplementedError, "#{self}.#{__method__}" + end + + # @yield when Rails application is running in test environment. + def self.clean! + return true unless Rails.env.test? + yield + end + + def self.query(q, **kwargs) + raise NotImplementedError, "#{self}.#{__method__}" + end + end + end +end diff --git a/lib/bulkrax/persistence_layer/active_fedora_adapter.rb b/lib/bulkrax/persistence_layer/active_fedora_adapter.rb new file mode 100644 index 000000000..1aad45031 --- /dev/null +++ b/lib/bulkrax/persistence_layer/active_fedora_adapter.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Bulkrax + module PersistenceLayer + class ActiveFedoraAdapter < AbstractAdapter + def self.find(id) + ActiveFedora::Base.find(id) + rescue ActiveFedora::ObjectNotFoundError => e + raise PersistenceLayer::RecordNotFound, e.message + end + + def self.query(q, **kwargs) + ActiveFedora::SolrService.query(q, **kwargs) + end + + def self.clean! + super do + ActiveFedora::Cleaner.clean! + end + end + + def self.solr_name(field_name) + ActiveFedora.index_field_mapper.solr_name(field_name) + end + end + end +end diff --git a/lib/bulkrax/persistence_layer/valkyrie_adapter.rb b/lib/bulkrax/persistence_layer/valkyrie_adapter.rb new file mode 100644 index 000000000..cfa334bbd --- /dev/null +++ b/lib/bulkrax/persistence_layer/valkyrie_adapter.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Bulkrax + module PersistenceLayer + class ValkyrieAdapter < AbstractAdapter + end + end +end diff --git a/spec/lib/bulkrax_spec.rb b/spec/lib/bulkrax_spec.rb index d914ee9be..4701b004a 100644 --- a/spec/lib/bulkrax_spec.rb +++ b/spec/lib/bulkrax_spec.rb @@ -197,4 +197,12 @@ expect(returned_value).to eq("file") end end + + context '.persistence_adapter' do + subject { described_class.persistence_adapter } + it { is_expected.to respond_to(:find) } + it { is_expected.to respond_to(:query) } + it { is_expected.to respond_to(:solr_name) } + it { is_expected.to respond_to(:clean!) } + end end