Skip to content

Commit

Permalink
Move shelving to a background job
Browse files Browse the repository at this point in the history
So that web archiving shelving jobs don't time out.
  • Loading branch information
jcoyne committed Oct 30, 2019
1 parent 39a32d4 commit 4c13d5c
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 28 deletions.
11 changes: 3 additions & 8 deletions app/controllers/shelves_controller.rb
Expand Up @@ -6,20 +6,15 @@ class ShelvesController < ApplicationController

def create
if @item.is_a?(Dor::Item)
ShelvingService.shelve(@item)
head :no_content
result = BackgroundJobResult.create
ShelveJob.perform_later(druid: @item.pid, background_job_result: result)
head :created, location: result
else
render json: {
errors: [
{ title: 'Invalid item type', detail: "A Dor::Item is required but you provided '#{@item.class}'" }
]
}, status: :unprocessable_entity
end
rescue ShelvingService::ContentDirNotFoundError => e
render json: {
errors: [
{ title: 'Content directory not found', detail: e.message }
]
}, status: :unprocessable_entity
end
end
22 changes: 22 additions & 0 deletions app/jobs/shelve_job.rb
@@ -0,0 +1,22 @@
# frozen_string_literal: true

# Move files to Stacks in the background
class ShelveJob < ApplicationJob
queue_as :default

# @param [String] druid the identifier of the item to be published
# @param [BackgroundJobResult] background_job_result identifier of a background job result to store status info
def perform(druid:, background_job_result:)
background_job_result.processing!

begin
item = Dor.find(druid)
ShelvingService.shelve(item)
rescue ShelvingService::ContentDirNotFoundError => e
background_job_result.output = { errors: [{ title: 'Content directory not found', detail: e.message }] }
background_job_result.complete!
end

background_job_result.complete!
end
end
14 changes: 12 additions & 2 deletions openapi.json
Expand Up @@ -130,6 +130,7 @@
],
"summary": "Get the manifest of the datastream from SDR",
"description": "",
"deprecated": true,
"operationId": "sdr#ds_manifest",
"responses": {
"200": {
Expand Down Expand Up @@ -730,8 +731,17 @@
"description": "",
"operationId": "shelves#create",
"responses": {
"204": {
"description": "The object was shelved"
"201": {
"description": "Shelving action started",
"headers": {
"Location": {
"description": "the status of the action is found at this URI",
"schema": {
"type": "string",
"format": "uri"
}
}
}
},
"422": {
"description": "The object you provided was not a Dor::Item and could not be shelved",
Expand Down
55 changes: 55 additions & 0 deletions spec/jobs/shelve_job_spec.rb
@@ -0,0 +1,55 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe ShelveJob, type: :job do
subject(:perform) { described_class.perform_now(druid: druid, background_job_result: result) }

let(:druid) { 'druid:mk420bs7601' }
let(:result) { create(:background_job_result) }
let(:item) { instance_double(Dor::Item) }

before do
allow(Dor).to receive(:find).with(druid).and_return(item)
allow(result).to receive(:processing!)
end

context 'with no errors' do
before do
allow(ShelvingService).to receive(:shelve)
perform
end

it 'marks the job as processing' do
expect(result).to have_received(:processing!).once
end

it 'invokes the ShelvingService' do
expect(ShelvingService).to have_received(:shelve).with(item).once
end

it 'marks the job as complete' do
expect(result).to be_complete
end

it 'has no output' do
expect(result.output).to be_blank
end
end

context 'with errors returned by ShelvingService' do
let(:error_message) { "file isn't where we looked" }

before do
allow(ShelvingService).to receive(:shelve).and_raise(ShelvingService::ContentDirNotFoundError, error_message)
end

it 'marks the job as errored' do
perform
expect(result).to have_received(:processing!).once
expect(ShelvingService).to have_received(:shelve).with(item).once
expect(result).to be_complete
expect(result.output[:errors]).to eq [{ 'detail' => error_message, 'title' => 'Content directory not found' }]
end
end
end
24 changes: 6 additions & 18 deletions spec/requests/shelving_spec.rb
Expand Up @@ -5,7 +5,7 @@
RSpec.describe 'Shelve object' do
before do
allow(Dor).to receive(:find).and_return(object)
allow(ShelvingService).to receive(:shelve)
allow(ShelveJob).to receive(:perform_later)
end

let(:object) { Dor::Item.new(pid: 'druid:1234') }
Expand All @@ -18,29 +18,17 @@
expect(response).to have_http_status(:unprocessable_entity)
json = JSON.parse(response.body)
expect(json['errors'].first['detail']).to eq("A Dor::Item is required but you provided 'Dor::Collection'")
expect(ShelvingService).not_to have_received(:shelve)
expect(ShelveJob).not_to have_received(:perform_later)
end
end

context 'when the request is successful' do
it 'calls ShelvingService and returns 204' do
it 'calls ShelvingService and returns201' do
post '/v1/objects/druid:1234/shelve', headers: { 'Authorization' => "Bearer #{jwt}" }

expect(response).to have_http_status(:no_content)
expect(ShelvingService).to have_received(:shelve)
end
end

context "when the file can't be found" do
before do
allow(ShelvingService).to receive(:shelve).and_raise(ShelvingService::ContentDirNotFoundError, "file isn't where we looked")
end

it 'returns a 422 error' do
post '/v1/objects/druid:1234/shelve', headers: { 'Authorization' => "Bearer #{jwt}" }
expect(response).to have_http_status(:unprocessable_entity)
json = JSON.parse(response.body)
expect(json['errors'].first['detail']).to eq("file isn't where we looked")
expect(response).to have_http_status(:created)
expect(ShelveJob).to have_received(:perform_later)
.with(druid: 'druid:1234', background_job_result: BackgroundJobResult)
end
end
end

0 comments on commit 4c13d5c

Please sign in to comment.