Skip to content

Commit

Permalink
Adding NBP push connector
Browse files Browse the repository at this point in the history
  • Loading branch information
Mathis-Z committed Jun 17, 2024
1 parent f01dcb4 commit 961f8a3
Show file tree
Hide file tree
Showing 20 changed files with 521 additions and 4 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ gem 'sassc-rails'
gem 'shakapacker', '8.0.0'
gem 'simple_form'
gem 'slim-rails'
gem 'solid_queue'
gem 'sprockets-rails'
gem 'terser'
gem 'turbolinks'
Expand Down
13 changes: 13 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ GEM
docile (1.4.0)
drb (2.2.1)
erubi (1.12.0)
et-orbi (1.2.11)
tzinfo
execjs (2.9.1)
factory_bot (6.4.6)
activesupport (>= 5.0.0)
Expand All @@ -164,6 +166,9 @@ GEM
faraday-net_http (3.1.0)
net-http
ffi (1.16.3)
fugit (1.11.0)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
glob (0.4.1)
globalid (1.2.1)
activesupport (>= 6.1)
Expand Down Expand Up @@ -313,6 +318,7 @@ GEM
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
raabro (1.4.0)
racc (1.8.0)
rack (3.0.11)
rack-mini-profiler (3.3.1)
Expand Down Expand Up @@ -500,6 +506,12 @@ GEM
slim_lint (0.27.0)
rubocop (>= 1.0, < 2.0)
slim (>= 3.0, < 6.0)
solid_queue (0.3.2)
activejob (>= 7.1)
activerecord (>= 7.1)
concurrent-ruby (>= 1.3.1)
fugit (~> 1.11.0)
railties (>= 7.1)
sorted_set (1.0.3)
rbtree
set (~> 1.0)
Expand Down Expand Up @@ -627,6 +639,7 @@ DEPENDENCIES
simplecov
slim-rails
slim_lint
solid_queue
sprockets-rails
stackprof
terser
Expand Down
4 changes: 4 additions & 0 deletions app/jobs/application_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

class ApplicationJob < ActiveJob::Base
end
11 changes: 11 additions & 0 deletions app/jobs/nbp_delete_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class NbpDeleteJob < ApplicationJob
retry_on Faraday::Error, wait: :polynomially_longer

def perform(task_uuid)
Nbp::PushConnector.instance.delete_task!(task_uuid)

Rails.logger.debug { "Task with UUID #{task_uuid} deleted from NBP" }
end
end
9 changes: 9 additions & 0 deletions app/jobs/nbp_push_all_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class NbpPushAllJob < ApplicationJob
def perform
Task.find_each(batch_size: 50) do |task|
NbpPushJob.perform_later task
end
end
end
13 changes: 13 additions & 0 deletions app/jobs/nbp_push_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class NbpPushJob < ApplicationJob
retry_on Faraday::Error, wait: :polynomially_longer

def perform(task)
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') {|xml| LomService::ExportLom.call(task:, xml:) }

Nbp::PushConnector.instance.push_lom!(builder.to_xml)

Rails.logger.debug { "Task ##{task.id} \"#{task}\" pushed to NBP" }
end
end
21 changes: 20 additions & 1 deletion app/models/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
class Task < ApplicationRecord
acts_as_taggable_on :state

before_validation :lowercase_language
after_destroy_commit :remove_metadata_from_nbp, if: -> { Nbp::PushConnector.enabled? }
after_save_commit :sync_metadata_with_nbp, if: -> { Nbp::PushConnector.enabled? }

validates :title, presence: true

validates :uuid, uniqueness: true

before_validation :lowercase_language
validates :language, format: {with: /\A[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*\z/, message: :not_de_or_us}
validate :primary_language_tag_in_iso639?

Expand Down Expand Up @@ -102,6 +105,22 @@ def self.ransackable_associations(_auth_object = nil)
%w[labels]
end

def sync_metadata_with_nbp
if access_level_public?
publish_metadata_to_nbp
elsif saved_change_to_access_level?
remove_metadata_from_nbp
end
end

def publish_metadata_to_nbp
NbpPushJob.perform_later self
end

def remove_metadata_from_nbp
NbpDeleteJob.perform_later uuid
end

# This method creates a duplicate while leaving permissions and ownership unchanged
def duplicate
dup.tap do |task|
Expand Down
4 changes: 4 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false

# Use a real queuing backend for Active Job (and separate queues per environment).
config.active_job.queue_adapter = :solid_queue
config.active_job.queue_name_prefix = 'codeharbor_development'

config.action_mailer.perform_caching = false

# Print deprecation notices to the Rails logger.
Expand Down
4 changes: 2 additions & 2 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@
# config.cache_store = :mem_cache_store

# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "codeharbor_production"
config.active_job.queue_adapter = :solid_queue
config.active_job.queue_name_prefix = 'codeharbor_production'

config.action_mailer.perform_caching = false

Expand Down
4 changes: 4 additions & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test

# Use a real queuing backend for Active Job (and separate queues per environment).
config.active_job.queue_adapter = :solid_queue
config.active_job.queue_name_prefix = 'codeharbor_test'

config.action_mailer.perform_caching = false

# Tell Action Mailer not to deliver emails to the real world.
Expand Down
3 changes: 3 additions & 0 deletions config/puma.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@
# - Phased Restarts are only supported in cluster mode with multiple workers (i.e., not in development).
# - The Puma binary won't be upgraded on phased restarts, but since we have the unattended-upgrades, this is not a major issue.
# - See https://github.com/casperisfine/puma/blob/master/docs/restart.md.

# Run Solid Queue's supervisor
plugin :solid_queue
11 changes: 11 additions & 0 deletions config/settings/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,14 @@ omniauth:
private_key: ~
oai_pmh:
admin_mail: admin@example.org
nbp:
push_connector:
enable: true
client_id: testing_client_id
client_secret: testing_client_secret
token_path: 'https://test.provider/token'
api_host: 'https://test.api.host'
source:
organization: test_organization
name: CodeHarbor
slug: CoHaP2
18 changes: 18 additions & 0 deletions config/solid_queue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# default: &default
# dispatchers:
# - polling_interval: 1
# batch_size: 500
# workers:
# - queues: "*"
# threads: 3
# processes: 1
# polling_interval: 0.1
#
# development:
# <<: *default
#
# test:
# <<: *default
#
# production:
# <<: *default
103 changes: 103 additions & 0 deletions db/migrate/20240609104039_create_solid_queue_tables.solid_queue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# frozen_string_literal: true

# This migration comes from solid_queue (originally 20231211200639)
class CreateSolidQueueTables < ActiveRecord::Migration[7.0]
def change
create_table :solid_queue_jobs do |t|
t.string :queue_name, null: false
t.string :class_name, null: false, index: true
t.text :arguments
t.integer :priority, default: 0, null: false
t.string :active_job_id, index: true
t.datetime :scheduled_at
t.datetime :finished_at, index: true
t.string :concurrency_key

t.timestamps

t.index %i[queue_name finished_at], name: 'index_solid_queue_jobs_for_filtering'
t.index %i[scheduled_at finished_at], name: 'index_solid_queue_jobs_for_alerting'
end

create_table :solid_queue_scheduled_executions do |t|
t.references :job, index: {unique: true}, null: false
t.string :queue_name, null: false
t.integer :priority, default: 0, null: false
t.datetime :scheduled_at, null: false

t.datetime :created_at, null: false

t.index %i[scheduled_at priority job_id], name: 'index_solid_queue_dispatch_all'
end

create_table :solid_queue_ready_executions do |t|
t.references :job, index: {unique: true}, null: false
t.string :queue_name, null: false
t.integer :priority, default: 0, null: false

t.datetime :created_at, null: false

t.index %i[priority job_id], name: 'index_solid_queue_poll_all'
t.index %i[queue_name priority job_id], name: 'index_solid_queue_poll_by_queue'
end

create_table :solid_queue_claimed_executions do |t|
t.references :job, index: {unique: true}, null: false
t.bigint :process_id
t.datetime :created_at, null: false

t.index %i[process_id job_id]
end

create_table :solid_queue_blocked_executions do |t|
t.references :job, index: {unique: true}, null: false
t.string :queue_name, null: false
t.integer :priority, default: 0, null: false
t.string :concurrency_key, null: false
t.datetime :expires_at, null: false

t.datetime :created_at, null: false

t.index %i[expires_at concurrency_key], name: 'index_solid_queue_blocked_executions_for_maintenance'
end

create_table :solid_queue_failed_executions do |t|
t.references :job, index: {unique: true}, null: false
t.text :error
t.datetime :created_at, null: false
end

create_table :solid_queue_pauses do |t|
t.string :queue_name, null: false, index: {unique: true}
t.datetime :created_at, null: false
end

create_table :solid_queue_processes do |t|
t.string :kind, null: false
t.datetime :last_heartbeat_at, null: false, index: true
t.bigint :supervisor_id, index: true

t.integer :pid, null: false
t.string :hostname
t.text :metadata

t.datetime :created_at, null: false
end

create_table :solid_queue_semaphores do |t|
t.string :key, null: false, index: {unique: true}
t.integer :value, default: 1, null: false
t.datetime :expires_at, null: false, index: true

t.timestamps

t.index %i[key value], name: 'index_solid_queue_semaphores_on_key_and_value'
end

add_foreign_key :solid_queue_blocked_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade
add_foreign_key :solid_queue_claimed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade
add_foreign_key :solid_queue_failed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade
add_foreign_key :solid_queue_ready_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade
add_foreign_key :solid_queue_scheduled_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

# This migration comes from solid_queue (originally 20240110143450)
class AddMissingIndexToBlockedExecutions < ActiveRecord::Migration[7.1]
def change
add_index :solid_queue_blocked_executions, %i[concurrency_key priority job_id], name: 'index_solid_queue_blocked_executions_for_release'
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

# This migration comes from solid_queue (originally 20240218110712)
class CreateRecurringExecutions < ActiveRecord::Migration[7.1]
def change
create_table :solid_queue_recurring_executions do |t|
t.references :job, index: {unique: true}, null: false
t.string :task_key, null: false
t.datetime :run_at, null: false
t.datetime :created_at, null: false

t.index %i[task_key run_at], unique: true
end

add_foreign_key :solid_queue_recurring_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade
end
end
Loading

0 comments on commit 961f8a3

Please sign in to comment.