bulkrax 5.0.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/bulkrax/entries_controller.rb +4 -2
  3. data/app/controllers/bulkrax/exporters_controller.rb +13 -9
  4. data/app/controllers/bulkrax/importers_controller.rb +10 -10
  5. data/app/helpers/bulkrax/application_helper.rb +1 -1
  6. data/app/helpers/bulkrax/importers_helper.rb +2 -2
  7. data/app/helpers/bulkrax/validation_helper.rb +4 -4
  8. data/app/jobs/bulkrax/create_relationships_job.rb +78 -59
  9. data/app/jobs/bulkrax/delete_job.rb +1 -1
  10. data/app/jobs/bulkrax/export_work_job.rb +2 -2
  11. data/app/jobs/bulkrax/import_file_set_job.rb +1 -1
  12. data/app/jobs/bulkrax/import_work_job.rb +20 -7
  13. data/app/jobs/bulkrax/importer_job.rb +2 -2
  14. data/app/jobs/bulkrax/schedule_relationships_job.rb +2 -1
  15. data/app/matchers/bulkrax/application_matcher.rb +1 -0
  16. data/app/models/bulkrax/csv_entry.rb +93 -24
  17. data/app/models/bulkrax/exporter.rb +18 -19
  18. data/app/models/bulkrax/importer.rb +5 -5
  19. data/app/models/bulkrax/importer_run.rb +6 -0
  20. data/app/models/bulkrax/oai_entry.rb +14 -2
  21. data/app/models/bulkrax/pending_relationship.rb +4 -0
  22. data/app/models/concerns/bulkrax/dynamic_record_lookup.rb +3 -1
  23. data/app/models/concerns/bulkrax/export_behavior.rb +6 -4
  24. data/app/models/concerns/bulkrax/has_matchers.rb +1 -0
  25. data/app/models/concerns/bulkrax/import_behavior.rb +6 -3
  26. data/app/models/concerns/bulkrax/importer_exporter_behavior.rb +9 -1
  27. data/app/models/concerns/bulkrax/status_info.rb +9 -4
  28. data/app/parsers/bulkrax/application_parser.rb +14 -16
  29. data/app/parsers/bulkrax/bagit_parser.rb +6 -17
  30. data/app/parsers/bulkrax/csv_parser.rb +43 -111
  31. data/app/parsers/bulkrax/oai_dc_parser.rb +2 -2
  32. data/app/parsers/bulkrax/parser_export_record_set.rb +281 -0
  33. data/app/parsers/bulkrax/xml_parser.rb +9 -5
  34. data/app/services/bulkrax/remove_relationships_for_importer.rb +4 -2
  35. data/app/views/bulkrax/entries/show.html.erb +1 -1
  36. data/app/views/bulkrax/exporters/_form.html.erb +60 -45
  37. data/app/views/bulkrax/exporters/edit.html.erb +1 -1
  38. data/app/views/bulkrax/exporters/index.html.erb +2 -2
  39. data/app/views/bulkrax/exporters/new.html.erb +1 -1
  40. data/app/views/bulkrax/exporters/show.html.erb +3 -3
  41. data/app/views/bulkrax/importers/_bagit_fields.html.erb +13 -12
  42. data/app/views/bulkrax/importers/_csv_fields.html.erb +13 -12
  43. data/app/views/bulkrax/importers/_form.html.erb +5 -5
  44. data/app/views/bulkrax/importers/_oai_fields.html.erb +12 -10
  45. data/app/views/bulkrax/importers/_xml_fields.html.erb +12 -11
  46. data/app/views/bulkrax/importers/show.html.erb +18 -16
  47. data/app/views/bulkrax/shared/_collection_entries_tab.html.erb +6 -6
  48. data/app/views/bulkrax/shared/_file_set_entries_tab.html.erb +6 -6
  49. data/app/views/bulkrax/shared/_work_entries_tab.html.erb +6 -6
  50. data/config/locales/bulkrax.en.yml +26 -0
  51. data/lib/bulkrax/entry_spec_helper.rb +190 -0
  52. data/lib/bulkrax/version.rb +1 -1
  53. data/lib/bulkrax.rb +124 -45
  54. data/lib/generators/bulkrax/templates/config/initializers/bulkrax.rb +1 -1
  55. data/lib/tasks/reset.rake +1 -1
  56. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49a1f0ccc806cf73a7872a634c8c2819dac62f98f0a9dc163e7ada8931d9b1fe
4
- data.tar.gz: ecf5c8ad3e4864110665cfb5c6c5f6329e3b868414815bba163646db839400e7
3
+ metadata.gz: c9794c69e891f2397ac94398676f49db008e83b7a6df16e7a08f0ab393c148ca
4
+ data.tar.gz: fd2d48507add6bcbc7557f9240951d174c488e456579af65e20bb6cdc6f3c080
5
5
  SHA512:
6
- metadata.gz: df394e4fbbc6ca0a71eb595c075c5181d24098b1ab889ff185da10991ec01c2eaf60239658564838b67df4c0a421306de923d2eab4bbeffafb31321acb9ba1ff
7
- data.tar.gz: 35b691e96d0e59f83efadc35364283239f7f741ab4bf9d859756dacc8483e380090512cd10bf3b6ec4ce81936d00c88eb4d1ed96742c384e0f3082028ffdcf45
6
+ metadata.gz: 3b07a4178650201c48602c9bb9df29135a5cc51bc6954355732bd6ae5fa918c5fd4c88d187e305b7ee2877ca995818d7ec3a476e92ec173c7569c0a15ca229a2
7
+ data.tar.gz: 324393aeb341d82b23e6391cbe1ec2a64d3e55a61400330f1656f46b3bb22cd0c6e7335cfeaf1b3b12e6ca5faefea5405b96e1100b1df138dd4c5a87fd522d76
@@ -5,10 +5,10 @@ require_dependency "oai"
5
5
 
6
6
  module Bulkrax
7
7
  class EntriesController < ApplicationController
8
- include Hyrax::ThemedLayoutController
8
+ include Hyrax::ThemedLayoutController if defined?(::Hyrax)
9
9
  before_action :authenticate_user!
10
10
  before_action :check_permissions
11
- with_themed_layout 'dashboard'
11
+ with_themed_layout 'dashboard' if defined?(::Hyrax)
12
12
 
13
13
  def show
14
14
  if params[:importer_id].present?
@@ -23,6 +23,7 @@ module Bulkrax
23
23
  @importer = Importer.find(params[:importer_id])
24
24
  @entry = Entry.find(params[:id])
25
25
 
26
+ return unless defined?(::Hyrax)
26
27
  add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
27
28
  add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
28
29
  add_breadcrumb 'Importers', bulkrax.importers_path
@@ -35,6 +36,7 @@ module Bulkrax
35
36
  @exporter = Exporter.find(params[:exporter_id])
36
37
  @entry = Entry.find(params[:id])
37
38
 
39
+ return unless defined?(::Hyrax)
38
40
  add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
39
41
  add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
40
42
  add_breadcrumb 'Exporters', bulkrax.exporters_path
@@ -4,24 +4,26 @@ require_dependency "bulkrax/application_controller"
4
4
 
5
5
  module Bulkrax
6
6
  class ExportersController < ApplicationController
7
- include Hyrax::ThemedLayoutController
7
+ include Hyrax::ThemedLayoutController if defined?(::Hyrax)
8
8
  include Bulkrax::DownloadBehavior
9
9
  before_action :authenticate_user!
10
10
  before_action :check_permissions
11
11
  before_action :set_exporter, only: [:show, :edit, :update, :destroy]
12
- with_themed_layout 'dashboard'
12
+ with_themed_layout 'dashboard' if defined?(::Hyrax)
13
13
 
14
14
  # GET /exporters
15
15
  def index
16
16
  @exporters = Exporter.all
17
17
 
18
- add_exporter_breadcrumbs
18
+ add_exporter_breadcrumbs if defined?(::Hyrax)
19
19
  end
20
20
 
21
21
  # GET /exporters/1
22
22
  def show
23
- add_exporter_breadcrumbs
24
- add_breadcrumb @exporter.name
23
+ if defined?(::Hyrax)
24
+ add_exporter_breadcrumbs
25
+ add_breadcrumb @exporter.name
26
+ end
25
27
 
26
28
  @work_entries = @exporter.entries.where(type: @exporter.parser.entry_class.to_s).page(params[:work_entries_page]).per(30)
27
29
  @collection_entries = @exporter.entries.where(type: @exporter.parser.collection_entry_class.to_s).page(params[:collections_entries_page]).per(30)
@@ -31,16 +33,18 @@ module Bulkrax
31
33
  # GET /exporters/new
32
34
  def new
33
35
  @exporter = Exporter.new
34
-
36
+ return unless defined?(::Hyrax)
35
37
  add_exporter_breadcrumbs
36
38
  add_breadcrumb 'New'
37
39
  end
38
40
 
39
41
  # GET /exporters/1/edit
40
42
  def edit
41
- add_exporter_breadcrumbs
42
- add_breadcrumb @exporter.name, bulkrax.exporter_path(@exporter.id)
43
- add_breadcrumb 'Edit'
43
+ if defined?(::Hyrax)
44
+ add_exporter_breadcrumbs
45
+ add_breadcrumb @exporter.name, bulkrax.exporter_path(@exporter.id)
46
+ add_breadcrumb 'Edit'
47
+ end
44
48
 
45
49
  # Correctly populate export_source_collection input
46
50
  @collection = Collection.find(@exporter.export_source) if @exporter.export_source.present? && @exporter.export_from == 'collection'
@@ -6,7 +6,7 @@ require_dependency 'oai'
6
6
  module Bulkrax
7
7
  # rubocop:disable Metrics/ClassLength
8
8
  class ImportersController < ApplicationController
9
- include Hyrax::ThemedLayoutController
9
+ include Hyrax::ThemedLayoutController if defined?(::Hyrax)
10
10
  include Bulkrax::DownloadBehavior
11
11
  include Bulkrax::API
12
12
  include Bulkrax::ValidationHelper
@@ -16,14 +16,14 @@ module Bulkrax
16
16
  before_action :authenticate_user!, unless: -> { api_request? }
17
17
  before_action :check_permissions
18
18
  before_action :set_importer, only: [:show, :edit, :update, :destroy]
19
- with_themed_layout 'dashboard'
19
+ with_themed_layout 'dashboard' if defined?(::Hyrax)
20
20
 
21
21
  # GET /importers
22
22
  def index
23
23
  @importers = Importer.all
24
24
  if api_request?
25
25
  json_response('index')
26
- else
26
+ elsif defined?(::Hyrax)
27
27
  add_importer_breadcrumbs
28
28
  end
29
29
  end
@@ -32,14 +32,13 @@ module Bulkrax
32
32
  def show
33
33
  if api_request?
34
34
  json_response('show')
35
- else
35
+ elsif defined?(::Hyrax)
36
36
  add_importer_breadcrumbs
37
37
  add_breadcrumb @importer.name
38
-
39
- @work_entries = @importer.entries.where(type: @importer.parser.entry_class.to_s).page(params[:work_entries_page]).per(30)
40
- @collection_entries = @importer.entries.where(type: @importer.parser.collection_entry_class.to_s).page(params[:collections_entries_page]).per(30)
41
- @file_set_entries = @importer.entries.where(type: @importer.parser.file_set_entry_class.to_s).page(params[:file_set_entries_page]).per(30)
42
38
  end
39
+ @work_entries = @importer.entries.where(type: @importer.parser.entry_class.to_s).page(params[:work_entries_page]).per(30)
40
+ @collection_entries = @importer.entries.where(type: @importer.parser.collection_entry_class.to_s).page(params[:collections_entries_page]).per(30)
41
+ @file_set_entries = @importer.entries.where(type: @importer.parser.file_set_entry_class.to_s).page(params[:file_set_entries_page]).per(30)
43
42
  end
44
43
 
45
44
  # GET /importers/new
@@ -47,7 +46,7 @@ module Bulkrax
47
46
  @importer = Importer.new
48
47
  if api_request?
49
48
  json_response('new')
50
- else
49
+ elsif defined?(::Hyrax)
51
50
  add_importer_breadcrumbs
52
51
  add_breadcrumb 'New'
53
52
  end
@@ -57,7 +56,7 @@ module Bulkrax
57
56
  def edit
58
57
  if api_request?
59
58
  json_response('edit')
60
- else
59
+ elsif defined?(::Hyrax)
61
60
  add_importer_breadcrumbs
62
61
  add_breadcrumb @importer.name, bulkrax.importer_path(@importer.id)
63
62
  add_breadcrumb 'Edit'
@@ -159,6 +158,7 @@ module Bulkrax
159
158
  # GET /importer/1/upload_corrected_entries
160
159
  def upload_corrected_entries
161
160
  @importer = Importer.find(params[:importer_id])
161
+ return unless defined?(::Hyrax)
162
162
  add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
163
163
  add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
164
164
  add_breadcrumb 'Importers', bulkrax.importers_path
@@ -3,7 +3,7 @@ require 'coderay'
3
3
 
4
4
  module Bulkrax
5
5
  module ApplicationHelper
6
- include ::Hyrax::HyraxHelperBehavior
6
+ include ::Hyrax::HyraxHelperBehavior if defined?(::Hyrax)
7
7
 
8
8
  def coderay(value, opts)
9
9
  CodeRay
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Bulkrax
4
4
  module ImportersHelper
5
- # borrowd from batch-importer https://github.com/samvera-labs/hyrax-batch_ingest/blob/main/app/controllers/hyrax/batch_ingest/batches_controller.rb
5
+ # borrowed from batch-importer https://github.com/samvera-labs/hyrax-batch_ingest/blob/main/app/controllers/hyrax/batch_ingest/batches_controller.rb
6
6
  def available_admin_sets
7
- # Restrict available_admin_sets to only those current user can desposit to.
7
+ # Restrict available_admin_sets to only those current user can deposit to.
8
8
  @available_admin_sets ||= Hyrax::Collections::PermissionsService.source_ids_for_deposit(ability: current_ability, source_type: 'admin_set').map do |admin_set_id|
9
9
  [AdminSet.find(admin_set_id).title.first, admin_set_id]
10
10
  end
@@ -5,10 +5,8 @@ module Bulkrax
5
5
  def valid_create_params?
6
6
  check_admin_set
7
7
  check_user
8
- return true if valid_importer? &&
9
- valid_commit? &&
10
- valid_name? &&
11
- valid_parser_klass? &&
8
+ return true if valid_importer? && valid_commit? &&
9
+ valid_name? && valid_parser_klass? &&
12
10
  valid_parser_fields?
13
11
  end
14
12
 
@@ -19,6 +17,8 @@ module Bulkrax
19
17
  end
20
18
 
21
19
  def check_admin_set
20
+ return unless defined?(::Hyrax)
21
+
22
22
  if params[:importer][:admin_set_id].blank?
23
23
  params[:importer][:admin_set_id] = AdminSet::DEFAULT_ID
24
24
  else
@@ -16,13 +16,32 @@ module Bulkrax
16
16
  # to either an instance of a Work or an instance of a Collection.
17
17
  # NOTE: In the context of this job, "identifier" is used to generically refer
18
18
  # to either a record's ID or an Bulkrax::Entry's source_identifier.
19
+ # Please override with your own job for custom/non-hyrax applications
20
+ # set Bulkrax config variable :relationship_job to your custom class
19
21
  class CreateRelationshipsJob < ApplicationJob
22
+ ##
23
+ # @api public
24
+ # @since v5.0.1
25
+ #
26
+ # Once we've created the relationships, should we then index the works's file_sets to ensure
27
+ # that we have the proper indexed values. This can help set things like `is_page_of_ssim` for
28
+ # IIIF manifest and search results of file sets.
29
+ #
30
+ # @note As of v5.0.1 the default behavior is to not perform this. That preserves past
31
+ # implementations. However, we might determine that we want to change the default
32
+ # behavior. Which would likely mean a major version change.
33
+ #
34
+ # @example
35
+ # # In config/initializers/bulkrax.rb
36
+ # Bulkrax::CreateRelationshipsJob.update_child_records_works_file_sets = true
37
+ #
38
+ # @see https://github.com/scientist-softserv/louisville-hyku/commit/128a9ef
39
+ class_attribute :update_child_records_works_file_sets, default: false
40
+
20
41
  include DynamicRecordLookup
21
42
 
22
43
  queue_as :import
23
44
 
24
- attr_accessor :child_records, :child_entry, :parent_record, :parent_entry, :importer_run_id
25
-
26
45
  # @param parent_identifier [String] Work/Collection ID or Bulkrax::Entry source_identifiers
27
46
  # @param importer_run [Bulkrax::ImporterRun] current importer run (needed to properly update counters)
28
47
  #
@@ -31,82 +50,82 @@ module Bulkrax
31
50
  # Whether the @base_entry is the parent or the child in the relationship is determined by the presence of a
32
51
  # parent_identifier or child_identifier param. For example, if a parent_identifier is passed, we know @base_entry
33
52
  # is the child in the relationship, and vice versa if a child_identifier is passed.
53
+ #
54
+ # rubocop:disable Metrics/MethodLength
34
55
  def perform(parent_identifier:, importer_run_id:) # rubocop:disable Metrics/AbcSize
35
- pending_relationships = Bulkrax::PendingRelationship.find_each.select do |rel|
36
- rel.importer_run_id == importer_run_id && rel.parent_id == parent_identifier
37
- end.sort_by(&:order)
38
-
39
- @importer_run_id = importer_run_id
40
- @parent_entry, @parent_record = find_record(parent_identifier, importer_run_id)
41
- @child_records = { works: [], collections: [] }
42
- pending_relationships.each do |rel|
43
- raise ::StandardError, %("#{rel}" needs either a child or a parent to create a relationship) if rel.child_id.nil? || rel.parent_id.nil?
44
- @child_entry, child_record = find_record(rel.child_id, importer_run_id)
45
- if child_record
46
- child_record.is_a?(::Collection) ? @child_records[:collections] << child_record : @child_records[:works] << child_record
56
+ importer_run = Bulkrax::ImporterRun.find(importer_run_id)
57
+ ability = Ability.new(importer_run.user)
58
+
59
+ parent_entry, parent_record = find_record(parent_identifier, importer_run_id)
60
+
61
+ number_of_successes = 0
62
+ number_of_failures = 0
63
+ errors = []
64
+
65
+ ActiveRecord::Base.uncached do
66
+ Bulkrax::PendingRelationship.where(parent_id: parent_identifier, importer_run_id: importer_run_id)
67
+ .ordered.find_each do |rel|
68
+ process(relationship: rel, importer_run_id: importer_run_id, parent_record: parent_record, ability: ability)
69
+ number_of_successes += 1
70
+ rescue => e
71
+ number_of_failures += 1
72
+ errors << e
47
73
  end
48
74
  end
49
75
 
50
- if (child_records[:collections].blank? && child_records[:works].blank?) || parent_record.nil?
76
+ # save record if members were added
77
+ parent_record.save! if @parent_record_members_added
78
+
79
+ # rubocop:disable Rails/SkipsModelValidations
80
+ if errors.present?
81
+ importer_run.increment!(:failed_relationships, number_of_failures)
82
+ parent_entry&.set_status_info(errors.last, importer_run)
83
+
84
+ # TODO: This can create an infinite job cycle, consider a time to live tracker.
51
85
  reschedule({ parent_identifier: parent_identifier, importer_run_id: importer_run_id })
52
86
  return false # stop current job from continuing to run after rescheduling
87
+ else
88
+ Bulkrax::ImporterRun.find(importer_run_id).increment!(:processed_relationships, number_of_successes)
53
89
  end
54
- @parent_entry ||= Bulkrax::Entry.where(identifier: parent_identifier,
55
- importerexporter_id: ImporterRun.find(importer_run_id).importer_id,
56
- importerexporter_type: "Bulkrax::Importer").first
57
- create_relationships
58
- pending_relationships.each(&:destroy)
59
- rescue ::StandardError => e
60
- parent_entry ? parent_entry.status_info(e) : child_entry.status_info(e)
61
- Bulkrax::ImporterRun.find(importer_run_id).increment!(:failed_relationships) # rubocop:disable Rails/SkipsModelValidations
90
+ # rubocop:enable Rails/SkipsModelValidations
62
91
  end
92
+ # rubocop:enable Metrics/MethodLength
63
93
 
64
94
  private
65
95
 
66
- def create_relationships
67
- if parent_record.is_a?(::Collection)
68
- collection_parent_work_child unless child_records[:works].empty?
69
- collection_parent_collection_child unless child_records[:collections].empty?
70
- else
71
- work_parent_work_child unless child_records[:works].empty?
72
- raise ::StandardError, 'a Collection may not be assigned as a child of a Work' if child_records[:collections].present?
73
- end
74
- end
96
+ def process(relationship:, importer_run_id:, parent_record:, ability:)
97
+ raise "#{relationship} needs a child to create relationship" if relationship.child_id.nil?
98
+ raise "#{relationship} needs a parent to create relationship" if relationship.parent_id.nil?
75
99
 
76
- def user
77
- @user ||= Bulkrax::ImporterRun.find(importer_run_id).importer.user
78
- end
100
+ _child_entry, child_record = find_record(relationship.child_id, importer_run_id)
101
+ raise "#{relationship} could not find child record" unless child_record
79
102
 
80
- # Work-Collection membership is added to the child as member_of_collection_ids
81
- # This is adding the reverse relationship, from the child to the parent
82
- def collection_parent_work_child
83
- child_work_ids = child_records[:works].map(&:id)
84
- parent_record.try(:reindex_extent=, Hyrax::Adapters::NestingIndexAdapter::LIMITED_REINDEX)
103
+ raise "Cannot add child collection (ID=#{relationship.child_id}) to parent work (ID=#{relationship.parent_id})" if child_record.collection? && parent_record.work?
85
104
 
86
- parent_record.add_member_objects(child_work_ids)
87
- ImporterRun.find(importer_run_id).increment!(:processed_relationships, child_work_ids.count) # rubocop:disable Rails/SkipsModelValidations
88
- end
105
+ ability.authorize!(:edit, child_record)
89
106
 
90
- # Collection-Collection membership is added to the as member_ids
91
- def collection_parent_collection_child
92
- child_records[:collections].each do |child_record|
93
- ::Hyrax::Collections::NestedCollectionPersistenceService.persist_nested_collection_for(parent: parent_record, child: child_record)
94
- ImporterRun.find(importer_run_id).increment!(:processed_relationships) # rubocop:disable Rails/SkipsModelValidations
95
- end
107
+ # We could do this outside of the loop, but that could lead to odd counter failures.
108
+ ability.authorize!(:edit, parent_record)
109
+
110
+ parent_record.is_a?(Collection) ? add_to_collection(child_record, parent_record) : add_to_work(child_record, parent_record)
111
+
112
+ child_record.file_sets.each(&:update_index) if update_child_records_works_file_sets? && child_record.respond_to?(:file_sets)
113
+ relationship.destroy
96
114
  end
97
115
 
98
- # Work-Work membership is added to the parent as member_ids
99
- def work_parent_work_child
100
- records_hash = {}
101
- child_records[:works].each_with_index do |child_record, i|
102
- records_hash[i] = { id: child_record.id }
103
- end
104
- attrs = { work_members_attributes: records_hash }
116
+ def add_to_collection(child_record, parent_record)
105
117
  parent_record.try(:reindex_extent=, Hyrax::Adapters::NestingIndexAdapter::LIMITED_REINDEX)
106
- env = Hyrax::Actors::Environment.new(parent_record, Ability.new(user), attrs)
118
+ child_record.member_of_collections << parent_record
119
+ child_record.save!
120
+ end
121
+
122
+ def add_to_work(child_record, parent_record)
123
+ return true if parent_record.ordered_members.to_a.include?(child_record)
107
124
 
108
- Hyrax::CurationConcern.actor.update(env)
109
- ImporterRun.find(importer_run_id).increment!(:processed_relationships, child_records[:works].count) # rubocop:disable Rails/SkipsModelValidations
125
+ parent_record.ordered_members << child_record
126
+ @parent_record_members_added = true
127
+ # TODO: Do we need to save the child record?
128
+ child_record.save!
110
129
  end
111
130
 
112
131
  def reschedule(parent_identifier:, importer_run_id:)
@@ -13,7 +13,7 @@ module Bulkrax
13
13
  entry.save!
14
14
  entry.importer.current_run = ImporterRun.find(importer_run.id)
15
15
  entry.importer.record_status
16
- entry.status_info("Deleted", ImporterRun.find(importer_run.id))
16
+ entry.set_status_info("Deleted", ImporterRun.find(importer_run.id))
17
17
  end
18
18
  # rubocop:enable Rails/SkipsModelValidations
19
19
  end
@@ -29,9 +29,9 @@ module Bulkrax
29
29
  return entry if exporter_run.enqueued_records.positive?
30
30
 
31
31
  if exporter_run.failed_records.positive?
32
- exporter_run.exporter.status_info('Complete (with failures)')
32
+ exporter_run.exporter.set_status_info('Complete (with failures)')
33
33
  else
34
- exporter_run.exporter.status_info('Complete')
34
+ exporter_run.exporter.set_status_info('Complete')
35
35
  end
36
36
 
37
37
  return entry
@@ -41,7 +41,7 @@ module Bulkrax
41
41
  ImportFileSetJob.set(wait: (entry.import_attempts + 1).minutes).perform_later(entry_id, importer_run_id)
42
42
  else
43
43
  ImporterRun.find(importer_run_id).decrement!(:enqueued_records) # rubocop:disable Rails/SkipsModelValidations
44
- entry.status_info(e)
44
+ entry.set_status_info(e)
45
45
  end
46
46
  end
47
47
 
@@ -5,24 +5,37 @@ module Bulkrax
5
5
  queue_as :import
6
6
 
7
7
  # rubocop:disable Rails/SkipsModelValidations
8
+ #
9
+ # @note Yes, we are calling {ImporterRun.find} each time. these were on purpose to prevent race
10
+ # conditions on the database update. If you do not re-find (or at least reload) the object
11
+ # on each increment, the count can get messed up. Let's say there are two jobs A and B and
12
+ # a counter set to 2.
13
+ #
14
+ # - A grabs the importer_run (line 10)
15
+ # - B grabs the importer_run (line 10)
16
+ # - A Finishes the build, does the increment (now the counter is 3)
17
+ # - B Finishes the build, does the increment (now the counter is 3 again) and thus a count
18
+ # is lost.
19
+ #
20
+ # @see https://codingdeliberately.com/activerecord-increment/
21
+ # @see https://github.com/samvera-labs/bulkrax/commit/5c2c795452e13a98c9217fdac81ae2f5aea031a0#r105848236
8
22
  def perform(entry_id, run_id, time_to_live = 3, *)
9
23
  entry = Entry.find(entry_id)
10
- importer_run = ImporterRun.find(run_id)
11
24
  entry.build
12
25
  if entry.status == "Complete"
13
- importer_run.increment!(:processed_records)
14
- importer_run.increment!(:processed_works)
26
+ ImporterRun.find(run_id).increment!(:processed_records)
27
+ ImporterRun.find(run_id).increment!(:processed_works)
15
28
  else
16
29
  # do not retry here because whatever parse error kept you from creating a work will likely
17
30
  # keep preventing you from doing so.
18
- importer_run.increment!(:failed_records)
19
- importer_run.increment!(:failed_works)
31
+ ImporterRun.find(run_id).increment!(:failed_records)
32
+ ImporterRun.find(run_id).increment!(:failed_works)
20
33
  end
21
34
  # Regardless of completion or not, we want to decrement the enqueued records.
22
- importer_run.decrement!(:enqueued_records) unless importer_run.enqueued_records <= 0
35
+ ImporterRun.find(run_id).decrement!(:enqueued_records) unless ImporterRun.find(run_id).enqueued_records <= 0
23
36
 
24
37
  entry.save!
25
- entry.importer.current_run = importer_run
38
+ entry.importer.current_run = ImporterRun.find(run_id)
26
39
  entry.importer.record_status
27
40
  rescue Bulkrax::CollectionsCreatedError => e
28
41
  Rails.logger.warn("#{self.class} entry_id: #{entry_id}, run_id: #{run_id} encountered #{e.class}: #{e.message}")
@@ -12,8 +12,8 @@ module Bulkrax
12
12
  import(importer, only_updates_since_last_import)
13
13
  update_current_run_counters(importer)
14
14
  schedule(importer) if importer.schedulable?
15
- rescue CSV::MalformedCSVError => e
16
- importer.status_info(e)
15
+ rescue ::CSV::MalformedCSVError => e
16
+ importer.set_status_info(e)
17
17
  end
18
18
 
19
19
  def import(importer, only_updates_since_last_import)
@@ -9,7 +9,8 @@ module Bulkrax
9
9
  return reschedule(importer_id) unless pending_num.zero?
10
10
 
11
11
  importer.last_run.parents.each do |parent_id|
12
- CreateRelationshipsJob.perform_later(parent_identifier: parent_id, importer_run_id: importer.last_run.id)
12
+ Bulkrax.relationship_job_class.constantize.perform_later(parent_identifier: parent_id,
13
+ importer_run_id: importer.last_run.id)
13
14
  end
14
15
  end
15
16
 
@@ -102,6 +102,7 @@ module Bulkrax
102
102
 
103
103
  # Only add valid resource types
104
104
  def parse_resource_type(src)
105
+ ActiveSupport::Deprecation.warn('#parse_resource_type will be removed in Bulkrax v6.0.0')
105
106
  Hyrax::ResourceTypesService.label(src.to_s.strip.titleize)
106
107
  rescue KeyError
107
108
  nil