Skip to content

Commit

Permalink
Bring over CDL files
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyf committed Mar 1, 2024
1 parent 8d89aa5 commit 17bf6cf
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 0 deletions.
50 changes: 50 additions & 0 deletions app/jobs/create_group_and_add_members_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

##
# This class is responsible for assigning a conceptually "private" group to the
# members of of the {Cdl} work.
#
# The reason for creating this group is when a person gains access to the CDL
# (via the lending application) it is more performant to add the person to a
# group than it is to add the person directly to each of the underlying files.
class CreateGroupAndAddMembersJob < ApplicationJob
RETRY_MAX = 5

queue_as :default

def perform(cdl_id, retries = 0)
work = Cdl.where(id: cdl_id).first
return if work.nil?

page_count = work.file_sets.first.page_count.first.to_i
child_model = work.iiif_print_config.pdf_split_child_model
child_works_count = work.members.select { |member| member.is_a?(child_model) }.count

if page_count == child_works_count
group = Hyrax::Group.find_or_create_by!(name: work.id)
work.read_groups = [group.name]

work.members.each do |member|
assign_read_groups(member, group.name)
end

work.save
group.save
else
return if retries > RETRY_MAX

retries += 1
CreateGroupAndAddMembersJob.set(wait: 10.minutes).perform_later(cdl_id, retries)
end
end

private

def assign_read_groups(member, group_name)
member.read_groups = [group_name]
member.save
member.members.each do |sub_member|
assign_read_groups(sub_member, group_name)
end
end
end
52 changes: 52 additions & 0 deletions app/jobs/iiif_print/create_relationships_job_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

# OVERRIDE IIIF Print v1.0.0 to call CreateGroupAndAddMembersJob

module IiifPrint
module Jobs
module CreateRelationshipsJobDecorator
def perform(parent_id:, parent_model:, child_model:, retries: 0, **)
@parent_id = parent_id
@parent_model = parent_model
@child_model = child_model
@retries = retries + 1

@number_of_successes = 0
@number_of_failures = 0
@parent_record_members_added = false
@errors = []

# Because we need our children in the correct order, we can't create any
# relationships until all child works have been created.
if completed_child_data
# add the members
add_children_to_parent
if @number_of_failures.zero? && @number_of_successes == @pending_children.count
# remove pending relationships upon valid completion
@pending_children.each(&:destroy)
elsif @number_of_failures.zero? && @number_of_successes > @pending_children.count
# remove pending relationships but raise error that too many relationships formed
@pending_children.each(&:destroy)
raise "CreateRelationshipsJob for parent id: #{@parent_id} " \
"added #{@number_of_successes} children, " \
"expected #{@pending_children} children."
else
# report failures & keep pending relationships
raise "CreateRelationshipsJob failed for parent id: #{@parent_id} " \
"had #{@number_of_successes} successes & #{@number_of_failures} failures, " \
"with errors: #{@errors}. Wanted #{@pending_children} children."
end

# OVERRIDE begin
CreateGroupAndAddMembersJob.set(wait: 2.minutes).perform_later(parent_id) if parent_model == 'Cdl'
# OVERRIDE end
else
# if we aren't ready yet, reschedule the job and end this one normally
reschedule_job
end
end
end
end
end

IiifPrint::Jobs::CreateRelationshipsJob.prepend(IiifPrint::Jobs::CreateRelationshipsJobDecorator)
19 changes: 19 additions & 0 deletions lib/tasks/create_group_and_add_members.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

# CREATE_GROUP_FOR=tenant rake hyku:cdl:create_group_and_add_members[id1.id2.id3]
# NOTE: we are using period separations because comma separates don't seem to work
# without the CREATE_GROUP_FOR env var, it will default to 'blc' tenant
namespace :hyku do
namespace :cdl do
desc 'Enqueue CreateGroupAndAddMembersJob for each provided ID'
task :create_group_and_add_members, [:ids] => :environment do |_, args|
tenant = ENV['CREATE_GROUPS_FOR'] || 'blc'
switch!(tenant)

ids = args[:ids].split('.').map(&:strip)
ids.each do |id|
CreateGroupAndAddMembersJob.perform_later(id)
end
end
end
end
77 changes: 77 additions & 0 deletions spec/jobs/create_group_and_add_members_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

RSpec.describe CreateGroupAndAddMembersJob, type: :job do
subject(:job) { described_class.new(work.id) }

let(:work) do
work = FactoryBot.create(:cdl, title: ['Test CDL'])
work.ordered_members << file_set
work.save
work
end
let(:split_work_factory) { work.iiif_print_config.pdf_split_child_model.to_s.underscore }
let(:file_set) { FactoryBot.create(:file_set, title: ['Test File Set']) }
let(:work_page_1) { FactoryBot.create(split_work_factory, title: ["#{work.id} - #{work.title.first} Page 1"]) }
let(:work_page_2) { FactoryBot.create(split_work_factory, title: ["#{work.id} - #{work.title.first} Page 2"]) }
let(:file_set_page_1) { FactoryBot.create(:file_set, title: ["page1.jpg"]) }
let(:file_set_page_2) { FactoryBot.create(:file_set, title: ["page2.jpg"]) }

before { allow_any_instance_of(FileSet).to receive(:page_count).and_return(["2"]) }

describe '#perform' do
context 'when has all its child works' do
before do
work.ordered_members << work_page_1
work.ordered_members << work_page_2
work.save
work_page_1.ordered_members << file_set_page_1
work_page_1.save
work_page_2.ordered_members << file_set_page_2
work_page_2.save
end

it 'creates a group' do
expect { job.perform(work.id) }.to change { Hyrax::Group.count }.by(1)
end

it 'assigns the group to the work read_groups' do
job.perform(work.id)

expect(work.reload.read_groups).to eq([work.id])
end

it "assigns the group to the read_groups of each work's member" do
job.perform(work.id)

expect(work_page_1.reload.read_groups).to eq([work.id])
expect(work_page_2.reload.read_groups).to eq([work.id])
end

it "assigns the group to the read_groups of each work's member's member" do
job.perform(work.id)

expect(file_set_page_1.reload.read_groups).to eq([work.id])
expect(file_set_page_2.reload.read_groups).to eq([work.id])
end
end

context 'when does not have all its child works' do
before do
work.ordered_members << work_page_1
work.save
end

it 'retries the job' do
expect(described_class).to receive(:set).with(wait: 10.minutes).and_return(described_class)

job.perform(work.id)
end

it 'does not retry the job more than 5 times' do
expect(described_class).not_to receive(:set)

job.perform(work.id, 6)
end
end
end
end
30 changes: 30 additions & 0 deletions spec/jobs/iiif_print/create_relationships_job_decorator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

# rubocop:disable RSpec/FilePath
RSpec.describe IiifPrint::Jobs::CreateRelationshipsJobDecorator, type: :decorator do
describe '#perform' do
subject(:job) { IiifPrint::Jobs::CreateRelationshipsJob.new }

let(:parent) { FactoryBot.create(:cdl) }
let(:child) { FactoryBot.create(:generic_work) }

after do
job.perform(parent_id: parent.id, parent_model: parent.class.to_s, child_model: child.class)
end

context 'when parent_model is Cdl' do
it 'calls CreateGroupAndAddMembersJob' do
expect(CreateGroupAndAddMembersJob).to receive(:set).with(wait: 2.minutes).and_return(CreateGroupAndAddMembersJob)
end
end

context 'when parent_model is not Cdl' do
let(:parent) { FactoryBot.create(:generic_work) }

it 'does not call CreateGroupAndAddMembersJob' do
expect(CreateGroupAndAddMembersJob).not_to receive(:set)
end
end
end
end
# rubocop:enable RSpec/FilePath
21 changes: 21 additions & 0 deletions spec/tasks/create_group_and_add_members_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require 'rails_helper'
require 'rake'

RSpec.describe 'hyku:cdl:create_group_and_add_members' do
before do
Rake.application.rake_require "tasks/create_group_and_add_members"
Rake::Task.define_task(:environment)
end

let :run_rake_task do
Rake::Task["hyku:cdl:create_group_and_add_members"].reenable
Rake::Task["hyku:cdl:create_group_and_add_members"].invoke('id1.id2.id3')
end

it "invoke CreateGroupAndAddMembersJob" do
expect(CreateGroupAndAddMembersJob).to receive(:perform_later).exactly(3).times
run_rake_task
end
end

0 comments on commit 17bf6cf

Please sign in to comment.