-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
30
spec/jobs/iiif_print/create_relationships_job_decorator_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |