Skip to content

Commit 5be5afa

Browse files
authored
Merge pull request mlibrary#9 from mlibrary/feature/job_error
queue item error reporting
2 parents 4784a0e + 56c270c commit 5be5afa

File tree

5 files changed

+108
-101
lines changed

5 files changed

+108
-101
lines changed

app/controllers/v1/queue_items_controller.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ def index
99
def show
1010
@queue_item = QueueItem.find(params[:id])
1111
authorize @queue_item
12-
if @queue_item.bag
13-
head 303, location: v1_bag_url(@queue_item.bag)
14-
else
15-
render template: "v1/queue_items/show", status: 200
16-
end
12+
render template: "v1/queue_items/show", status: 200
1713
end
1814

1915
# POST /v1/requests/:bag_id/complete

app/jobs/bag_move_job.rb

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
class BagMoveJob < ApplicationJob
22
def perform(queue_item, src_path, dest_path)
3-
File.rename(src_path,dest_path)
43

5-
# When a bag is just a completed request
6-
# - start a transaction that updates the request to complete
7-
# - move the bag into place
8-
# - success: commit the transaction
9-
# - failure (exception) - transaction automatically rolls back
10-
queue_item.transaction do
11-
binding.pry
12-
queue_item.bag = bag_type(queue_item).create!(
13-
bag_id: queue_item.request.bag_id,
14-
user: queue_item.user,
15-
storage_location: dest_path,
16-
external_id: queue_item.request.external_id
17-
)
4+
begin
5+
File.rename(src_path,dest_path)
6+
7+
# When a bag is just a completed request
8+
# - start a transaction that updates the request to complete
9+
# - move the bag into place
10+
# - success: commit the transaction
11+
# - failure (exception) - transaction automatically rolls back
12+
queue_item.transaction do
13+
queue_item.bag = bag_type(queue_item).create!(
14+
bag_id: queue_item.request.bag_id,
15+
user: queue_item.user,
16+
storage_location: dest_path,
17+
external_id: queue_item.request.external_id,
18+
)
19+
queue_item.status = :done
20+
queue_item.save!
21+
end
22+
rescue => exception
23+
# attempt to log
24+
queue_item.error = exception.to_s
25+
queue_item.status = :failed
1826
queue_item.save!
27+
# re-raise
28+
raise exception
1929
end
2030
end
2131

lib/uploader.rb

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ def upload
1717
req = make_request
1818
rsync_bag(req["upload_link"])
1919
qitem = complete_request(req)
20-
bag = wait_for_bag(qitem)
21-
p bag
20+
print_result(wait_for_bag(qitem))
2221
end
2322

2423
def bag_id
@@ -29,6 +28,14 @@ def bag_id
2928

3029
attr_accessor :request_params, :api_key, :bag_path
3130

31+
def print_result(qitem_result)
32+
if qitem_result["status"] == "DONE"
33+
pp chipmunk_get(qitem_result["bag"])
34+
else
35+
pp qitem_result
36+
end
37+
end
38+
3239
def require_chipmunk_bag_tags(tags)
3340
["External-Identifier",
3441
"Bag-ID",
@@ -70,18 +77,14 @@ def complete_request(request)
7077
end
7178

7279
def wait_for_bag(qitem)
80+
result = qitem
7381
loop do
7482
# update qitem
75-
result = chipmunk_get("/v1/queue/#{qitem["id"]}")
76-
break if qitem["status"] != "PENDING"
83+
return result if result["status"] != "PENDING"
7784
puts "Waiting for queue item to be processed"
7885
sleep 10
86+
result = chipmunk_get("/v1/queue/#{qitem["id"]}")
7987
end
80-
81-
# TODO: error h&&ling
82-
# get 200 or 303
83-
84-
# get /bags/:bag_id, display
8588
end
8689

8790
def chipmunk_post(endpoint,params = {})
@@ -104,9 +107,15 @@ def follow_redir_and_parse(response)
104107
end
105108

106109
def chipmunk_request(method,endpoint,**kwargs)
110+
begin
107111
follow_redir_and_parse(RestClient::Request.execute(method: method,
108112
url: CHIPMUNK_URL + endpoint,
109113
headers: auth_header,
110114
**kwargs))
115+
rescue RestClient::InternalServerError => e
116+
puts e.to_s
117+
puts JSON.parse(e.response)["exception"]
118+
exit 1
119+
end
111120
end
112121
end

spec/controllers/v1/queue_items_controller_spec.rb

Lines changed: 4 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -54,79 +54,10 @@
5454
end
5555

5656
context "queue_item has a bag (is complete)" do
57-
before(:each) do
58-
request.headers.merge! auth_header
59-
get :show, params: {id: record.id}
60-
end
61-
62-
context "as unauthenticated user" do
63-
include_context "as unauthenticated user"
64-
let(:record) { done_proc.call }
65-
it "returns 401" do
66-
expect(response).to have_http_status(401)
67-
end
68-
it "renders nothing" do
69-
expect(response).to render_template(nil)
70-
end
71-
end
72-
73-
context "as underprivileged user" do
74-
include_context "as underprivileged user"
75-
76-
context "the record belongs to the user" do
77-
let(:record) { done_proc.call(user) }
78-
it "returns 303" do
79-
expect(response).to have_http_status(303)
80-
end
81-
it "correctly sets the location header" do
82-
expect(response.location).to eql(v1_bag_url(record.bag))
83-
end
84-
it "renders nothing" do
85-
expect(response).to render_template(nil)
86-
end
87-
end
88-
89-
context "the record does not belong to the user" do
90-
let(:record) { done_proc.call }
91-
it "returns 403" do
92-
expect(response).to have_http_status(403)
93-
end
94-
it "renders nothing" do
95-
expect(response).to render_template(nil)
96-
end
97-
end
98-
99-
end
100-
101-
context "as admin" do
102-
include_context "as admin user"
103-
104-
context "the record belongs to the user" do
105-
let(:record) { done_proc.call(user) }
106-
it "returns 303" do
107-
expect(response).to have_http_status(303)
108-
end
109-
it "correctly sets the location header" do
110-
expect(response.location).to eql(v1_bag_url(record.bag))
111-
end
112-
it "renders nothing" do
113-
expect(response).to render_template(nil)
114-
end
115-
end
116-
117-
context "the record does not belong to the user" do
118-
let(:record) { done_proc.call }
119-
it "returns 303" do
120-
expect(response).to have_http_status(303)
121-
end
122-
it "correctly sets the location header" do
123-
expect(response.location).to eql(v1_bag_url(record.bag))
124-
end
125-
it "renders nothing" do
126-
expect(response).to render_template(nil)
127-
end
128-
end
129-
57+
it_behaves_like "a show endpoint" do
58+
let(:key) { :id }
59+
let(:factory) { done_proc }
60+
let(:assignee) { :queue_item }
13061
end
13162
end
13263

spec/jobs/bag_move_job_spec.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe BagMoveJob do
4+
let (:queue_item) { Fabricate(:queue_item) }
5+
let (:srcpath) { 'foo' }
6+
let (:destpath) { 'bar' }
7+
8+
class InjectedError < RuntimeError
9+
end
10+
11+
describe '#perform' do
12+
subject { described_class.perform_now(queue_item,srcpath,destpath) }
13+
14+
context "when the move succeeds" do
15+
before(:each) do
16+
allow(File).to receive(:rename).with(srcpath,destpath).and_return true
17+
end
18+
19+
it "moves the bag" do
20+
expect(File).to receive(:rename).with(srcpath,destpath)
21+
subject
22+
end
23+
24+
it "on success, updates the queue_item to status :done" do
25+
subject
26+
expect(queue_item.status).to eql("done")
27+
end
28+
end
29+
30+
context "when there is an error" do
31+
before(:each) do
32+
allow(File).to receive(:rename).with(srcpath,destpath).and_raise InjectedError, 'injected error'
33+
end
34+
35+
it "re-raises the exception" do
36+
expect { subject }.to raise_exception(InjectedError)
37+
end
38+
39+
it "updates the queue_item to status 'failed'" do
40+
begin
41+
subject
42+
rescue InjectedError
43+
end
44+
45+
expect(queue_item.status).to eql("failed")
46+
end
47+
48+
it "records the error in the queue_item" do
49+
50+
begin
51+
subject
52+
rescue InjectedError
53+
end
54+
55+
expect(queue_item.error).to match(/injected error/)
56+
end
57+
end
58+
59+
end
60+
end
61+

0 commit comments

Comments
 (0)