hyrax 5.1.0.pre.beta1 → 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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.dassie/.env +4 -0
  3. data/.dassie/Gemfile +12 -7
  4. data/.dassie/app/controllers/application_controller.rb +4 -0
  5. data/.dassie/app/helpers/hyrax_helper.rb +4 -0
  6. data/.dassie/app/models/ability.rb +4 -0
  7. data/.dassie/app/models/user.rb +11 -0
  8. data/.dassie/app/views/shared/_footer.html.erb +17 -0
  9. data/.dassie/config/application.rb +1 -1
  10. data/.dassie/config/database.yml +18 -0
  11. data/.dassie/config/environments/production.rb +1 -1
  12. data/.dassie/config/fedora.yml +6 -6
  13. data/.dassie/config/initializers/devise.rb +1 -0
  14. data/.dassie/config/initializers/profiler.rb +5 -0
  15. data/.dassie/config/locales/hyrax.en.yml +1 -1
  16. data/.dassie/config/puma.rb +55 -5
  17. data/.dassie/config/routes.rb +2 -0
  18. data/.dassie/db/migrate/20250328100249_user_roles.rb +20 -0
  19. data/.dassie/db/schema.rb +123 -109
  20. data/.github/workflows/lint-build-test.yml +34 -5
  21. data/.koppie/.env +1 -1
  22. data/.koppie/Gemfile +10 -6
  23. data/.koppie/app/controllers/application_controller.rb +4 -0
  24. data/.koppie/app/helpers/hyrax_helper.rb +4 -0
  25. data/.koppie/app/models/ability.rb +4 -0
  26. data/.koppie/app/models/user.rb +10 -0
  27. data/.koppie/app/views/shared/_footer.html.erb +17 -0
  28. data/.koppie/config/database.yml +2 -9
  29. data/.koppie/config/environments/development.rb +9 -0
  30. data/.koppie/config/environments/production.rb +1 -1
  31. data/.koppie/config/initializers/1_valkyrie.rb +5 -5
  32. data/.koppie/config/initializers/devise.rb +1 -1
  33. data/.koppie/config/initializers/profiler.rb +5 -0
  34. data/.koppie/config/locales/hyrax.en.yml +2 -2
  35. data/.koppie/config/puma.rb +26 -7
  36. data/.koppie/config/routes.rb +2 -0
  37. data/.koppie/db/schema.rb +109 -110
  38. data/CONTAINERS.md +10 -10
  39. data/Dockerfile +108 -50
  40. data/Gemfile +2 -1
  41. data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +1 -0
  42. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +2 -1
  43. data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +4 -4
  44. data/app/controllers/hyrax/file_sets_controller.rb +11 -0
  45. data/app/helpers/hyrax/hyrax_helper_behavior.rb +2 -2
  46. data/app/helpers/hyrax/trophy_helper.rb +1 -1
  47. data/app/jobs/concerns/hyrax/queued_job_behavior.rb +22 -0
  48. data/app/jobs/hyrax/propagate_change_depositor_job.rb +1 -1
  49. data/app/jobs/hyrax/queued_delete_job.rb +11 -0
  50. data/app/jobs/hyrax/queued_indexing_job.rb +11 -0
  51. data/app/jobs/migrate_files_to_valkyrie_job.rb +33 -21
  52. data/app/jobs/migrate_sipity_entity_job.rb +21 -0
  53. data/app/models/concerns/hyrax/ability.rb +4 -2
  54. data/app/models/concerns/hyrax/solr_document_behavior.rb +5 -2
  55. data/app/models/hyrax/file_metadata.rb +22 -7
  56. data/app/services/hyrax/analytics/ga4/base.rb +1 -1
  57. data/app/services/hyrax/analytics/ga4.rb +5 -1
  58. data/app/services/hyrax/change_depositor_service.rb +1 -1
  59. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +21 -13
  60. data/app/services/hyrax/custom_queries/find_ids_by_model.rb +31 -6
  61. data/app/services/hyrax/edit_permissions_service.rb +9 -8
  62. data/app/services/hyrax/workflow/workflow_factory.rb +3 -3
  63. data/app/services/migrate_resource_service.rb +1 -1
  64. data/app/views/_user_util_links.html.erb +2 -1
  65. data/app/views/hyrax/admin/analytics/collection_reports/_top_collections.html.erb +3 -7
  66. data/app/views/hyrax/admin/analytics/work_reports/_top_file_set_downloads.html.erb +3 -6
  67. data/app/views/hyrax/admin/analytics/work_reports/_top_works.html.erb +2 -3
  68. data/app/views/hyrax/admin/analytics/work_reports/_work_files.html.erb +1 -6
  69. data/app/views/hyrax/base/_social_media.html.erb +2 -0
  70. data/app/views/hyrax/base/iiif_viewers/_universal_viewer.html.erb +1 -1
  71. data/app/views/hyrax/dashboard/collections/_show_document_list_menu.html.erb +13 -12
  72. data/app/views/hyrax/my/_admin_set_action_menu.html.erb +31 -27
  73. data/app/views/hyrax/my/_collection_action_menu.html.erb +40 -35
  74. data/app/views/hyrax/my/_work_action_menu.html.erb +23 -22
  75. data/bin/db-migrate-seed.sh +1 -1
  76. data/bin/dev-entrypoint.sh +3 -0
  77. data/config/features.rb +50 -40
  78. data/config/initializers/indexing_adapter_initializer.rb +4 -0
  79. data/config/initializers/new_framework_defaults_7_2.rb +6 -4
  80. data/config/initializers/reform_rails_6_1_monkey_patch.rb +29 -0
  81. data/config/metadata/core_metadata.yaml +1 -0
  82. data/docker-compose-dassie.yml +6 -6
  83. data/docker-compose-koppie.yml +2 -2
  84. data/docker-compose-sirenia.yml +2 -2
  85. data/documentation/developing-your-hyrax-based-app.md +2 -2
  86. data/hyrax.gemspec +3 -3
  87. data/lib/freyja/persister.rb +11 -4
  88. data/lib/generators/hyrax/install_generator.rb +0 -5
  89. data/lib/generators/hyrax/templates/.env +1 -1
  90. data/lib/generators/hyrax/templates/config/initializers/1_valkyrie.rb +21 -19
  91. data/lib/generators/hyrax/templates/db/migrate/20170131142607_add_permission_template_to_sipity_workflow.rb.erb +1 -1
  92. data/lib/generators/hyrax/templates/db/migrate/20170810190549_update_collection_type_column_options.rb.erb +1 -1
  93. data/lib/generators/hyrax/templates/db/migrate/20230821153635_add_fields_to_counter_metric.rb.erb +1 -1
  94. data/lib/hyrax/configuration.rb +22 -7
  95. data/lib/hyrax/controlled_vocabulary/importer/language.rb +5 -1
  96. data/lib/hyrax/transactions/steps/add_file_sets.rb +2 -1
  97. data/lib/hyrax/version.rb +1 -1
  98. data/lib/hyrax.rb +1 -0
  99. data/lib/tasks/workflow.rake +1 -2
  100. data/lib/valkyrie/indexing/redis_queue/indexing_adapter.rb +144 -0
  101. data/lib/wings/valkyrie/query_service.rb +3 -4
  102. data/template.rb +1 -1
  103. metadata +28 -14
  104. data/.github/workflows/main.yml +0 -17
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ return if Rails::VERSION::MAJOR >= 7
4
+
5
+ # Taken from https://github.com/trailblazer/reform-rails/issues/86#issuecomment-763120151
6
+ # rubocop:disable Metrics/CyclomaticComplexity
7
+ # rubocop:disable Lint/UselessAssignment
8
+ module Reform
9
+ class Contract < Disposable::Twin
10
+ class Result
11
+ private
12
+
13
+ # this doesn't do nested errors (e.g. )
14
+ def filter_for(method, *args)
15
+ @results.collect { |r| r.public_send(method, *args).to_h }
16
+ .inject({}) { |hah, err| hah.merge(err) { |_key, old_v, new_v| (new_v.is_a?(Array) ? (old_v |= new_v) : old_v.merge(new_v)) } }
17
+ .find_all do |_k, v| # filter :nested=>{:something=>["too nested!"]} #DISCUSS: do we want that here?
18
+ if v.is_a?(Hash)
19
+ nested_errors = v.select { |attr_key, val| attr_key.is_a?(Integer) && val.is_a?(Array) && val.any? }
20
+ v = nested_errors.to_a if nested_errors.any?
21
+ end
22
+ v.is_a?(ActiveModel::DeprecationHandlingMessageArray)
23
+ end.to_h
24
+ end
25
+ end
26
+ end
27
+ end
28
+ # rubocop:enable Metrics/CyclomaticComplexity
29
+ # rubocop:disable Lint/UselessAssignment
@@ -20,4 +20,5 @@ attributes:
20
20
  type: string
21
21
  predicate: http://id.loc.gov/vocabulary/relators/dpt
22
22
  index_keys:
23
+ - "depositor_ssim"
23
24
  - "depositor_tesim"
@@ -6,7 +6,7 @@ services:
6
6
  args:
7
7
  - EXTRA_APK_PACKAGES=git less
8
8
  - BUNDLE_GEMFILE=Gemfile.dassie
9
- image: samvera/hyrax-dev
9
+ image: ghcr.io/samvera/hyrax-dev:${GITHUB_SHA:-latest}
10
10
  command: sh -c 'bundle exec puma -v -b tcp://0.0.0.0:3000'
11
11
  stdin_open: true
12
12
  tty: true
@@ -40,7 +40,7 @@ services:
40
40
  - hyrax
41
41
 
42
42
  worker:
43
- image: samvera/hyrax-dev
43
+ image: ghcr.io/samvera/hyrax-dev:${GITHUB_SHA:-latest}
44
44
  entrypoint: worker-entrypoint.sh
45
45
  command: sh -c 'bundle exec sidekiq'
46
46
  user: root
@@ -68,14 +68,14 @@ services:
68
68
  chrome:
69
69
  image: selenium/standalone-chromium:4
70
70
  environment:
71
- # - START_XVFB=false
71
+ # - START_XVFB=false
72
72
  - SE_NODE_SESSION_TIMEOUT=800
73
73
  - SE_ENABLE_TRACING=false
74
74
  - SE_ENABLE_BROWSER_LEFTOVERS_CLEANUP=true
75
75
  - SE_BROWSER_ARGS_DISABLE_DSHM=--disable-dev-shm-usage
76
76
  - SE_BROWSER_ARGS_HEADLESS=--headless=new
77
- # logging:
78
- # driver: none
77
+ # logging:
78
+ # driver: none
79
79
  volumes:
80
80
  - /dev/shm:/dev/shm
81
81
  shm_size: 2g
@@ -118,7 +118,7 @@ services:
118
118
  memcached:
119
119
  image: bitnami/memcached
120
120
  ports:
121
- - '11211:11211'
121
+ - "11211:11211"
122
122
  networks:
123
123
  - hyrax
124
124
 
@@ -8,7 +8,7 @@ services:
8
8
  args:
9
9
  - EXTRA_APK_PACKAGES=git less
10
10
  - BUNDLE_GEMFILE=Gemfile.koppie
11
- image: samvera/hyrax-dev
11
+ image: ghcr.io/samvera/hyrax-dev:${GITHUB_SHA:-latest}
12
12
  command: sh -c 'bundle exec puma -v -b tcp://0.0.0.0:3000'
13
13
  stdin_open: true
14
14
  tty: true
@@ -43,7 +43,7 @@ services:
43
43
  - koppie
44
44
 
45
45
  worker:
46
- image: samvera/hyrax-dev
46
+ image: ghcr.io/samvera/hyrax-dev:${GITHUB_SHA:-latest}
47
47
  entrypoint: worker-entrypoint.sh
48
48
  command: sh -c 'bundle exec sidekiq'
49
49
  user: root
@@ -8,7 +8,7 @@ services:
8
8
  args:
9
9
  - EXTRA_APK_PACKAGES=git less
10
10
  - BUNDLE_GEMFILE=Gemfile.koppie
11
- image: samvera/hyrax-dev
11
+ image: ghcr.io/samvera/hyrax-dev:${GITHUB_SHA:-latest}
12
12
  command: sh -c 'bundle exec puma -v -b tcp://0.0.0.0:3000'
13
13
  stdin_open: true
14
14
  tty: true
@@ -46,7 +46,7 @@ services:
46
46
  - sirenia
47
47
 
48
48
  worker:
49
- image: samvera/hyrax-dev
49
+ image: ghcr.io/samvera/hyrax-dev:${GITHUB_SHA:-latest}
50
50
  entrypoint: worker-entrypoint.sh
51
51
  command: sh -c 'bundle exec sidekiq'
52
52
  user: root
@@ -32,7 +32,7 @@ You can also try [Running Hyrax-based application in local VM](https://github.co
32
32
  During development, running only the dependent services in a container environment may be beneficial. This avoids potential headaches concerning file permissions and eases the use of debugging tools. The application generation instructions below use [Lando](https://lando.dev) to achieve this setup.
33
33
 
34
34
  This document contains instructions specific to setting up an app with __Hyrax
35
- v5.1.0-beta1__. If you are looking for instructions on installing a different
35
+ v5.2.0__. If you are looking for instructions on installing a different
36
36
  version, be sure to select the appropriate branch or tag from the drop-down
37
37
  menu above.
38
38
 
@@ -148,7 +148,7 @@ Generate a new Rails application using the template.
148
148
  **NOTE:** `HYRAX_SKIP_WINGS` is needed here to avoid loading the Wings compatibility layer during the application generation process.
149
149
 
150
150
  ```shell
151
- HYRAX_SKIP_WINGS=true rails _7.2.2.1_ new my_app --database=postgresql -m https://raw.githubusercontent.com/samvera/hyrax/hyrax-v5.1.0-beta1/template.rb
151
+ HYRAX_SKIP_WINGS=true rails _7.2.2.1_ new my_app --database=postgresql -m https://raw.githubusercontent.com/samvera/hyrax/hyrax-v5.2.0/template.rb
152
152
  ```
153
153
 
154
154
  Generating a new Rails application using Hyrax's template above takes cares of a number of steps for you, including:
data/hyrax.gemspec CHANGED
@@ -32,13 +32,13 @@ SUMMARY
32
32
  # NOTE: rails does not follow sem-ver conventions, it's
33
33
  # minor version releases can include breaking changes; see
34
34
  # http://guides.rubyonrails.org/maintenance_policy.html
35
- spec.add_dependency 'rails', '~> 7.2', '< 8.0'
35
+ spec.add_dependency 'rails', '> 6.1', '< 8.0'
36
36
 
37
37
  spec.add_dependency 'active-fedora', '~> 15.0'
38
38
  spec.add_dependency 'almond-rails', '~> 0.1'
39
39
  spec.add_dependency 'awesome_nested_set', '~> 3.1'
40
40
  spec.add_dependency 'blacklight', '~> 7.29'
41
- spec.add_dependency 'blacklight-gallery', '~> 4.7.0'
41
+ spec.add_dependency 'blacklight-gallery', '~> 4.6.4'
42
42
  spec.add_dependency 'breadcrumbs_on_rails', '~> 3.0'
43
43
  spec.add_dependency 'browse-everything', '>= 0.16', '< 2.0'
44
44
  spec.add_dependency 'carrierwave', '~> 1.0'
@@ -100,7 +100,7 @@ SUMMARY
100
100
  spec.add_development_dependency 'pg', '~> 1.2'
101
101
  spec.add_development_dependency 'rspec-activemodel-mocks', '~> 1.0'
102
102
  spec.add_development_dependency 'rspec-its', '~> 1.1'
103
- spec.add_development_dependency 'rspec-rails', '~> 7.0'
103
+ spec.add_development_dependency 'rspec-rails', '> 6.1'
104
104
  spec.add_development_dependency 'rspec_junit_formatter'
105
105
  spec.add_development_dependency "selenium-webdriver", '~> 4.4'
106
106
  spec.add_development_dependency 'i18n-debug'
@@ -13,6 +13,7 @@ module Freyja
13
13
  # was modified in the database between been read into memory and persisted
14
14
  # rubocop:disable Lint/UnusedMethodArgument
15
15
  def save(resource:, external_resource: false, perform_af_validation: false)
16
+ was_wings = resource.respond_to?(:wings?) && resource.wings?
16
17
  orm_object = resource_factory.from_resource(resource: resource)
17
18
  orm_object.transaction do
18
19
  orm_object.save!
@@ -23,18 +24,24 @@ module Freyja
23
24
  "Called from #{Gem.location_of_caller.join(':')}"
24
25
  end
25
26
  end
26
- convert_and_migrate_resource(orm_object)
27
+ convert_and_migrate_resource(orm_object, was_wings)
27
28
 
28
29
  rescue ActiveRecord::StaleObjectError
29
30
  raise Valkyrie::Persistence::StaleObjectError, "The object #{resource.id} has been updated by another process."
30
31
  end
31
32
  # rubocop:enable Lint/UnusedMethodArgument
32
33
 
33
- def convert_and_migrate_resource(orm_object)
34
+ def convert_and_migrate_resource(orm_object, was_wings)
34
35
  new_resource = resource_factory.to_resource(object: orm_object)
35
- if Hyrax.config.valkyrie_transition?
36
+ # if the resource was wings and is now a Valkyrie resource, we need to migrate sipity, files, and members
37
+ if Hyrax.config.valkyrie_transition? && was_wings && !new_resource.wings?
36
38
  MigrateFilesToValkyrieJob.perform_later(new_resource) if new_resource.is_a?(Hyrax::FileSet) && new_resource.file_ids.size == 1 && new_resource.file_ids.first.id.to_s.match('/files/')
37
- MigrateResourcesJob.perform_later(ids: new_resource.member_ids.map(&:to_s)) if new_resource.is_a?(Hyrax::Work)
39
+ # migrate any members if the resource is a Hyrax work
40
+ if new_resource.is_a?(Hyrax::Work)
41
+ member_ids = new_resource.member_ids.map(&:to_s)
42
+ MigrateResourcesJob.perform_later(ids: member_ids) unless member_ids.empty?
43
+ MigrateSipityEntityJob.perform_now(id: new_resource.id.to_s)
44
+ end
38
45
  end
39
46
  new_resource
40
47
  end
@@ -209,10 +209,5 @@ module Hyrax
209
209
  gem 'dotenv-rails', '~> 2.8'
210
210
  end
211
211
  end
212
-
213
- def support_analytics
214
- gem 'google-protobuf', force_ruby_platform: true # required because google-protobuf is not compatible with Alpine linux
215
- gem 'grpc', force_ruby_platform: true # required because grpc is not compatible with Alpine linux
216
- end
217
212
  end
218
213
  end
@@ -1,6 +1,6 @@
1
1
  CH12N_TOOL=fits_servlet
2
2
  DATABASE_URL=postgresql://postgres@localhost:5437/hyrax-dev?pool=5
3
- FCREPO_URL=http://fedoraAdmin:fedoraAdmin@fcrepo:8989/fcrepo/rest
3
+ FEDORA_URL=http://fedoraAdmin:fedoraAdmin@localhost:8989/fcrepo/rest
4
4
  FITS_SERVLET_URL=http://localhost:8085/fits
5
5
  HYRAX_ACTIVE_JOB_QUEUE=async
6
6
  REDIS_URL=redis://localhost:6384
@@ -32,7 +32,7 @@ Valkyrie::MetadataAdapter.register(
32
32
  # Valkyrie::MetadataAdapter.register(
33
33
  # Valkyrie::Persistence::Fedora::MetadataAdapter.new(
34
34
  # connection: ::Ldp::Client.new(Hyrax.config.fedora_connection_builder.call(
35
- # ENV.fetch('FCREPO_URL') { "http://localhost:8080/fcrepo/rest" }
35
+ # ENV.fetch('FEDORA_URL') { "http://localhost:8080/fcrepo/rest" }
36
36
  # )),
37
37
  # base_path: Rails.env,
38
38
  # schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new(Hyrax::SimpleSchemaLoader.new.permissive_schema_for_valkrie_adapter),
@@ -67,7 +67,7 @@ Valkyrie.config.metadata_adapter = ENV.fetch('VALKYRIE_METADATA_ADAPTER') { :pg_
67
67
  # Valkyrie::StorageAdapter.register(
68
68
  # Valkyrie::Storage::Fedora.new(
69
69
  # connection: ::Ldp::Client.new(Hyrax.config.fedora_connection_builder.call(
70
- # ENV.fetch('FCREPO_URL') { "http://localhost:8080/fcrepo/rest" }
70
+ # ENV.fetch('FEDORA_URL') { "http://localhost:8080/fcrepo/rest" }
71
71
  # )),
72
72
  # base_path: Rails.env,
73
73
  # fedora_version: 6.5,
@@ -86,21 +86,23 @@ Valkyrie.config.storage_adapter = ENV.fetch('VALKYRIE_STORAGE_ADAPTER') { :vers
86
86
 
87
87
  Valkyrie.config.indexing_adapter = :solr_index
88
88
 
89
- custom_queries = [Hyrax::CustomQueries::Navigators::CollectionMembers,
90
- Hyrax::CustomQueries::Navigators::ChildCollectionsNavigator,
91
- Hyrax::CustomQueries::Navigators::ParentCollectionsNavigator,
92
- Hyrax::CustomQueries::Navigators::ChildFileSetsNavigator,
93
- Hyrax::CustomQueries::Navigators::ChildWorksNavigator,
94
- Hyrax::CustomQueries::Navigators::ParentWorkNavigator,
95
- Hyrax::CustomQueries::Navigators::FindFiles,
96
- Hyrax::CustomQueries::FindAccessControl,
97
- Hyrax::CustomQueries::FindCollectionsByType,
98
- Hyrax::CustomQueries::FindFileMetadata,
99
- Hyrax::CustomQueries::FindIdsByModel,
100
- Hyrax::CustomQueries::FindManyByAlternateIds,
101
- Hyrax::CustomQueries::FindModelsByAccess,
102
- Hyrax::CustomQueries::FindCountBy,
103
- Hyrax::CustomQueries::FindByDateRange]
104
- custom_queries.each do |handler|
105
- Hyrax.query_service.custom_queries.register_query_handler(handler)
89
+ Rails.application.reloader.to_prepare do
90
+ custom_queries = [Hyrax::CustomQueries::Navigators::CollectionMembers,
91
+ Hyrax::CustomQueries::Navigators::ChildCollectionsNavigator,
92
+ Hyrax::CustomQueries::Navigators::ParentCollectionsNavigator,
93
+ Hyrax::CustomQueries::Navigators::ChildFileSetsNavigator,
94
+ Hyrax::CustomQueries::Navigators::ChildWorksNavigator,
95
+ Hyrax::CustomQueries::Navigators::ParentWorkNavigator,
96
+ Hyrax::CustomQueries::Navigators::FindFiles,
97
+ Hyrax::CustomQueries::FindAccessControl,
98
+ Hyrax::CustomQueries::FindCollectionsByType,
99
+ Hyrax::CustomQueries::FindFileMetadata,
100
+ Hyrax::CustomQueries::FindIdsByModel,
101
+ Hyrax::CustomQueries::FindManyByAlternateIds,
102
+ Hyrax::CustomQueries::FindModelsByAccess,
103
+ Hyrax::CustomQueries::FindCountBy,
104
+ Hyrax::CustomQueries::FindByDateRange]
105
+ custom_queries.each do |handler|
106
+ Hyrax.query_service.custom_queries.register_query_handler(handler)
107
+ end
106
108
  end
@@ -1,4 +1,4 @@
1
- class AddPermissionTemplateToSipityWorkflow < ActiveRecord::Migration<%= migration_version %>
1
+ class AddPermissionTemplateToSipityWorkflow < ActiveRecord::Migration[6.1]
2
2
  def change
3
3
  add_column :sipity_workflows, :permission_template_id, :integer, index: true
4
4
  remove_index :sipity_workflows, :name
@@ -1,4 +1,4 @@
1
- class UpdateCollectionTypeColumnOptions < ActiveRecord::Migration<%= migration_version %>
1
+ class UpdateCollectionTypeColumnOptions < ActiveRecord::Migration[6.1]
2
2
  def up
3
3
  change_column :hyrax_collection_types, :title, :string, unique: true
4
4
  change_column :hyrax_collection_types, :machine_id, :string, unique: true
@@ -1,4 +1,4 @@
1
- class AddFieldsToCounterMetric < ActiveRecord::Migration<%= migration_version %>
1
+ class AddFieldsToCounterMetric < ActiveRecord::Migration[6.1]
2
2
  def change
3
3
  add_column :hyrax_counter_metrics, :title, :string
4
4
  add_column :hyrax_counter_metrics, :year_of_publication, :integer, index: true
@@ -133,8 +133,23 @@ module Hyrax
133
133
  attr_writer :analytics_reporting
134
134
  attr_reader :analytics_reporting
135
135
  def analytics_reporting?
136
- @analytics_reporting ||=
136
+ @analytics_reporting ||= begin
137
+ required_env_vars = %w[
138
+ HYRAX_ANALYTICS_REPORTING
139
+ GOOGLE_ANALYTICS_ID
140
+ GOOGLE_ANALYTICS_PROPERTY_ID
141
+ ]
142
+
143
+ required_env_vars << if ENV['GOOGLE_ACCOUNT_JSON'].blank?
144
+ 'GOOGLE_ACCOUNT_JSON_PATH'
145
+ else
146
+ 'GOOGLE_ACCOUNT_JSON'
147
+ end
148
+
149
+ return false if required_env_vars.any? { |var| ENV.fetch(var, '').blank? }
150
+
137
151
  ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYRAX_ANALYTICS_REPORTING', false))
152
+ end
138
153
  end
139
154
 
140
155
  # Currently supports 'google' or 'matomo'
@@ -142,7 +157,7 @@ module Hyrax
142
157
  attr_writer :analytics_provider
143
158
  def analytics_provider
144
159
  @analytics_provider ||=
145
- ENV.fetch('HYRAX_ANALYTICS_PROVIDER', 'google')
160
+ ENV.fetch('HYRAX_ANALYTICS_PROVIDER', 'ga4')
146
161
  end
147
162
 
148
163
  ##
@@ -478,31 +493,31 @@ module Hyrax
478
493
  # Path on the local file system where derivatives will be stored
479
494
  attr_writer :derivatives_path
480
495
  def derivatives_path
481
- @derivatives_path ||= ENV.fetch('HYRAX_DERIVATIVES_PATH', Rails.root.join('tmp', 'derivatives'))
496
+ @derivatives_path ||= Pathname.new(ENV.fetch('HYRAX_DERIVATIVES_PATH', Rails.root.join('tmp', 'derivatives')))
482
497
  end
483
498
 
484
499
  # Path on the local file system where originals will be staged before being ingested into Fedora.
485
500
  attr_writer :working_path
486
501
  def working_path
487
- @working_path ||= ENV.fetch('HYRAX_UPLOAD_PATH', Rails.root.join('tmp', 'uploads'))
502
+ @working_path ||= Pathname.new(ENV.fetch('HYRAX_UPLOAD_PATH', Rails.root.join('tmp', 'uploads')))
488
503
  end
489
504
 
490
505
  # @todo do we use both upload_path and working path?
491
506
  # Path on the local file system where originals will be staged before being ingested into Fedora.
492
507
  attr_writer :upload_path
493
508
  def upload_path
494
- @upload_path ||= ->() { ENV.fetch('HYRAX_UPLOAD_PATH') { Rails.root.join('tmp', 'uploads') } }
509
+ @upload_path ||= ->() { Pathname.new(ENV.fetch('HYRAX_UPLOAD_PATH') { Rails.root.join('tmp', 'uploads') }) }
495
510
  end
496
511
 
497
512
  attr_writer :cache_path
498
513
  def cache_path
499
- @cache_path ||= ->() { ENV.fetch('HYRAX_CACHE_PATH') { Rails.root.join('tmp', 'cache') } }
514
+ @cache_path ||= ->() { Pathname.new(ENV.fetch('HYRAX_CACHE_PATH') { Rails.root.join('tmp', 'cache') }) }
500
515
  end
501
516
 
502
517
  # Path on the local file system where where log and banners will be stored.
503
518
  attr_writer :branding_path
504
519
  def branding_path
505
- @branding_path ||= ENV.fetch('HYRAX_BRANDING_PATH', Rails.root.join('public', 'branding'))
520
+ @branding_path ||= Pathname.new(ENV.fetch('HYRAX_BRANDING_PATH', Rails.root.join('public', 'branding')))
506
521
  end
507
522
 
508
523
  # @!endgroup
@@ -13,7 +13,11 @@ module Hyrax
13
13
  stdout_logger.formatter = proc do |_severity, _datetime, _progname, msg|
14
14
  "#{msg}\n"
15
15
  end
16
- ActiveSupport::BroadcastLogger.new(Hyrax.logger, stdout_logger)
16
+ if Rails.version >= '7.1'
17
+ ActiveSupport::BroadcastLogger.new(Hyrax.logger, stdout_logger)
18
+ else
19
+ Hyrax.logger.extend(ActiveSupport::Logger.broadcast(stdout_logger))
20
+ end
17
21
  end
18
22
 
19
23
  def import
@@ -20,10 +20,11 @@ module Hyrax
20
20
  ##
21
21
  # @param [Hyrax::Work] obj
22
22
  # @param [Enumerable<UploadedFile>] uploaded_files
23
- # @param [Enumerable<Hash>] file_set_params
23
+ # @param [Enumerable<Hash>] file_set_params or nil
24
24
  #
25
25
  # @return [Dry::Monads::Result]
26
26
  def call(obj, uploaded_files: [], file_set_params: [])
27
+ return Success(obj) if uploaded_files.empty? && file_set_params.blank? # Skip if no files to attach
27
28
  if @handler.new(work: obj).add(files: uploaded_files, file_set_params: file_set_params).attach
28
29
  file_sets = obj.member_ids.map do |member|
29
30
  Hyrax.query_service.find_by(id: member) if Hyrax.query_service.find_by(id: member).is_a? Hyrax::FileSet
data/lib/hyrax/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hyrax
3
- VERSION = '5.1.0-beta1'
3
+ VERSION = '5.2.0'
4
4
  end
data/lib/hyrax.rb CHANGED
@@ -23,6 +23,7 @@ require 'hyrax/valkyrie_can_can_adapter'
23
23
  require 'retriable'
24
24
  require 'valkyrie/indexing_adapter'
25
25
  require 'valkyrie/indexing/solr/indexing_adapter'
26
+ require 'valkyrie/indexing/redis_queue/indexing_adapter'
26
27
  require 'valkyrie/indexing/null_indexing_adapter'
27
28
 
28
29
  ##
@@ -3,8 +3,7 @@ namespace :hyrax do
3
3
  namespace :workflow do
4
4
  desc "Load workflow configuration into the database"
5
5
  task load: :environment do
6
- logger = Logger.new(STDOUT)
7
- logger.level = Logger::DEBUG
6
+ logger = Hyrax.logger || Logger.new(STDOUT, level: Logger::DEBUG)
8
7
  Hyrax::Workflow::WorkflowImporter.load_workflows(logger: logger)
9
8
  errors = Hyrax::Workflow::WorkflowImporter.load_errors
10
9
  abort("Failed to process all workflows:\n #{errors.join('\n ')}") unless errors.empty?
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie
3
+ module Indexing
4
+ module RedisQueue
5
+ class IndexingAdapter
6
+ ##
7
+ # @!attribute [r] connection
8
+ # @return [RSolr::Client]
9
+ attr_writer :connection
10
+ attr_accessor :index_queue_name, :delete_queue_name, :index_error_name, :delete_error_name
11
+
12
+ ##
13
+ # @param connection [RSolr::Client] The RSolr connection to index to.
14
+ def initialize(connection: nil, index_queue_name: 'toindex', delete_queue_name: 'todelete')
15
+ @connection = connection
16
+ @index_queue_name = index_queue_name
17
+ @delete_queue_name = delete_queue_name
18
+ @index_error_name = index_queue_name + "-error"
19
+ @delete_error_name = delete_queue_name + "-error"
20
+ end
21
+
22
+ def connection
23
+ @connection ||= default_connection
24
+ end
25
+
26
+ def save(resource:)
27
+ persist([resource])
28
+ end
29
+
30
+ def save_all(resources:)
31
+ persist(resources)
32
+ end
33
+
34
+ # Deletes a Solr Document using the ID
35
+ # @return [Array<Valkyrie::Resource>] resources which have been deleted from Solr
36
+ def delete(resource:)
37
+ connection.zadd(delete_queue_name, Time.current.to_i, resource.id.to_s)
38
+ end
39
+
40
+ # Delete the Solr index of all Documents
41
+ def wipe!
42
+ connection.del(index_queue_name)
43
+ connection.del(index_error_name)
44
+ connection.del(delete_queue_name)
45
+ connection.del(delete_error_name)
46
+ end
47
+
48
+ def reset!
49
+ self.connection = default_connection
50
+ end
51
+
52
+ def index_queue(size: 200)
53
+ set = connection.zpopmin(index_queue_name, size)
54
+ return [] if set.blank?
55
+ # we have to load these one at a time because find_all_by_id gets duplicates during wings transition
56
+ resources = set.map { |id, _time| Hyrax.query_service.find_by(id: id) }
57
+ solr_indexer = Valkyrie::IndexingAdapter.find(:solr_index)
58
+ solr_indexer.save_all(resources: resources)
59
+ solr_indexer.connection.commit
60
+ rescue
61
+ # if anything goes wrong, try to requeue the items
62
+ set.each { |id, time| connection.zadd(index_error_name, time, id) }
63
+ raise
64
+ end
65
+
66
+ # If a batch fails, try running them one at a time to get down to just records that really fail
67
+ def index_error_queue(size: 200)
68
+ @set = []
69
+ solr_indexer = Valkyrie::IndexingAdapter.find(:solr_index)
70
+
71
+ size.times do
72
+ @set = queue.connection.zpopmin(index_error_name, 1)
73
+ return [] if @set.blank?
74
+ # we have to load these one at a time because find_all_by_id gets duplicates during wings transition
75
+ resource = Hyrax.query_service.find_by(id: @set[0])
76
+ solr_indexer.save(resource: resource)
77
+ rescue
78
+ # if anything goes wrong, try to requeue the items
79
+ @set.each { |id, _time| queue.connection.zadd(index_error_name + "-twice", Time.now.to_i, id) }
80
+ end
81
+ solr_indexer.connection.commit
82
+ end
83
+
84
+ # We reach in to solr directly here to prevent needing to load the objects unnecessarily
85
+ def delete_queue(size: 200)
86
+ set = connection.zpopmin(delete_queue_name, size)
87
+ return [] if set.blank?
88
+ solr_indexer = Valkyrie::IndexingAdapter.find(:solr_index)
89
+ set.each do |id, _time|
90
+ solr_indexer.connection.delete_by_id id.to_s, { softCommit: true }
91
+ end
92
+ solr_indexer.connection.commit
93
+ rescue
94
+ # if anything goes wrong, try to requeue the items
95
+ set.each { |id, time| connection.zadd(delete_error_name, time, id) }
96
+ raise
97
+ end
98
+
99
+ # If a batch fails, try running them one at a time to get down to just records that really fail
100
+ def delete_error_queue(size: 200)
101
+ @set = []
102
+ size.times do
103
+ @set = connection.zpopmin(delete_error_name, 1)
104
+ return [] if @set.blank?
105
+ solr_indexer = Valkyrie::IndexingAdapter.find(:solr_index)
106
+ solr_indexer.connection.delete_by_id @set[0].to_s, { softCommit: true }
107
+ solr_indexer.connection.commit
108
+ rescue
109
+ # if anything goes wrong, try to requeue the items
110
+ @set.each { |id, _time| connection.zadd(delete_error_name, Time.now.to_i, id) }
111
+ end
112
+ end
113
+
114
+ def list_index
115
+ connection.zrange(index_queue_name, 0, -1, with_scores: true)
116
+ end
117
+
118
+ def list_delete
119
+ connection.zrange(delete_queue_name, 0, -1, with_scores: true)
120
+ end
121
+
122
+ def list_index_errors
123
+ connection.zrange(index_error_name, 0, -1, with_scores: true)
124
+ end
125
+
126
+ def list_delete_errors
127
+ connection.zrange(delete_error_name, 0, -1, with_scores: true)
128
+ end
129
+
130
+ private
131
+
132
+ def persist(resources)
133
+ resources.map do |r|
134
+ connection.zadd(index_queue_name, Time.current.to_i, r.id.to_s)
135
+ end
136
+ end
137
+
138
+ def default_connection
139
+ Hyrax.config.redis_connection
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -63,11 +63,10 @@ module Wings
63
63
  #
64
64
  # @param model [Class]
65
65
  # @return [Array<Valkyrie::Resource>]
66
- #
67
- # @note Due to implementation details, .find_all_of_model and .count_all_of_model may not
68
- # return the same number of results. Is that a bug? Probably.
69
66
  def find_all_of_model(model:)
70
- model_class_for(model).all.map do |obj|
67
+ ActiveFedora::Base
68
+ .where(has_model_ssim: [model_class_for(model).to_rdf_representation,
69
+ model.to_rdf_representation]).map do |obj|
71
70
  resource_factory.to_resource(object: obj)
72
71
  end
73
72
  end
data/template.rb CHANGED
@@ -4,6 +4,6 @@ insert_into_file 'config/application.rb', after: /config\.load_defaults [0-9.]+$
4
4
  "\n config.add_autoload_paths_to_load_path = true"
5
5
  end
6
6
 
7
- gem 'hyrax', '5.1.0-beta1'
7
+ gem 'hyrax', '5.2.0'
8
8
  run 'bundle install'
9
9
  generate 'hyrax:install', '-f'