Skip to content

Commit

Permalink
🎁 Add Bulkrax.persistence_adapter
Browse files Browse the repository at this point in the history
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:

- scientist-softserv/hykuup_knapsack#35
  • Loading branch information
jeremyf committed Jan 17, 2024
1 parent 0dae0f9 commit 9652f27
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 0 deletions.
32 changes: 32 additions & 0 deletions lib/bulkrax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -81,6 +111,8 @@ def config
:object_factory=,
:parsers,
:parsers=,
:persistence_adapter,
:persistence_adapter=,
:qa_controlled_properties,
:qa_controlled_properties=,
:related_children_field_mapping,
Expand Down
6 changes: 6 additions & 0 deletions lib/bulkrax/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 38 additions & 0 deletions lib/bulkrax/persistence_layer.rb
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions lib/bulkrax/persistence_layer/active_fedora_adapter.rb
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions lib/bulkrax/persistence_layer/valkyrie_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

module Bulkrax
module PersistenceLayer
class ValkyrieAdapter < AbstractAdapter
end
end
end
8 changes: 8 additions & 0 deletions spec/lib/bulkrax_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 9652f27

Please sign in to comment.