Skip to content

Commit

Permalink
Analysis jobs integration bug fixes
Browse files Browse the repository at this point in the history
- Handle bugs for invalid paths in analysis_jobs_results_controller.rb
- Clarified email message when retrying an analysis job
- Added URL rewriting for `/analysis_jobs` so that the client pages will
be correctly rendered on first load
- Added a stub for the client application index.html (since it is super
confusing during dev to get 404s for 'valid' links)
- Added acceptance tests that document the _pause_, _resume_, and
_retry_ functionality in the analysis jobs API
  • Loading branch information
atruskie committed Nov 25, 2016
1 parent 8b770bf commit f9e2036
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 48 deletions.
2 changes: 1 addition & 1 deletion app/controllers/analysis_jobs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def update
parameters = analysis_job_update_params

# allow the API to transition this analysis job to a new state.
# Used for suspending and resuming an analysis_job
# Used for suspending, resuming, and retrying an analysis_job
if parameters.key?(:overall_status)
@analysis_job.transition_to_state(parameters[:overall_status].to_sym)
parameters = parameters.except(:overall_status)
Expand Down
10 changes: 9 additions & 1 deletion app/controllers/analysis_jobs_results_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ def show
do_load_resource
do_authorize_instance(:show, @analysis_jobs_result)

if @analysis_jobs_result.nil?
respond_error(
:not_found,
"Could not find Audio Recording with id #{@audio_recording_id}",
{error_info: {audio_recording_id: params[@audio_recording_id]}})
return
end

request_params[:results_path] = '' unless request_params.include?(:results_path)
@results_path = request_params[:results_path]

Expand All @@ -50,7 +58,7 @@ def get_base_url_path
end

def show_items_as_results(is_head_request, analysis_job_items, opts)
analysis_job_id = analysis_job_items.first.analysis_job_id
analysis_job_id = @analysis_job_id
result_roots = BawWorkers::Config.analysis_cache_helper.possible_job_paths_dir({job_id: analysis_job_id})

ajis_as_hash = analysis_job_items.map do |item|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

%p
You are receiving this email because your analysis job has been scheduled to be <strong>retried</strong>.
Failed items in the analysis job have been restarted.
Failed, cancelled, or timed out items in the analysis job have been restarted.


%p
Expand Down
7 changes: 7 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ class Application < Rails::Application
# for generating documentation from tests
Raddocs.configuration.docs_dir = "doc/api"

def should_route_to_client(rack_env)
(rack_env['REQUEST_METHOD'] == 'GET' &&
!Mime::Type.parse(rack_env['HTTP_ACCEPT']).include?(Mime::JSON) &&
File.extname(rack_env['REQUEST_PATH']) == "")
end

# middleware to rewrite angular urls
# insert at the start of the Rack stack.
config.middleware.insert_before 0, Rack::Rewrite do
Expand All @@ -147,6 +153,7 @@ class Application < Rails::Application
rewrite /^\/library.*/i, '/listen_to/index.html'
rewrite /^\/demo.*/i, '/listen_to/index.html'
rewrite /^\/visualize.*/i, '/listen_to/index.html'
rewrite /^\/analysis_jobs.*/i, '/listen_to/index.html', if: Application.method(:should_route_to_client)
end

# allow any origin, with any header, to access the array of methods
Expand Down
44 changes: 1 addition & 43 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,49 +133,7 @@
# audio_recording_update_status: /audio_recordings/:id/update_status

# endpoints used by client:
# routes: {
# project: "/projects/{projectId}",
# site: {
# flattened: "/sites/{siteId}",
# nested: "/projects/{projectId}/sites/{siteId}"
# },
# audioRecording: {
# listShort: "/audio_recordings/{recordingId}",
# show: "/audio_recordings/{recordingId}",
# list: "/audio_recordings/"
# },
# audioEvent: {
# list: "/audio_recordings/{recordingId}/audio_events",
# show: "/audio_recordings/{recordingId}/audio_events/{audioEventId}",
# csv: "/audio_recordings/{recordingId}/audio_events/download.{format}",
# },
# tagging: {
# list: "/audio_recordings/{recordingId}/audio_events/{audioEventId}/taggings",
# show: "/audio_recordings/{recordingId}/audio_events/{audioEventId}/taggings/{taggingId}"
# },
# tag: {
# list: '/tags/',
# show: '/tags/{tagId}'
# },
# media: {
# show: "/audio_recordings/{recordingId}/media.{format}"
# },
# security: {
# ping: "/security/sign_in",
# signIn: "/my_account/sign_in"
# },
# user: {
# profile: "/my_account",
# settings: "/my_account/prefs"
# }
# },
# links: {
# projects: '/projects',
# home: '/',
# project: '/projects/{projectId}',
# site: '/projects/{projectId}/sites/{siteId}',
# userAccounts: '/user_accounts/{userId}'
# }
# see: https://github.com/QutBioacoustics/baw-client/blob/master/src/baw.paths.nobuild.js#L3

# placed above related resource so it does not conflict with (resource)/:id => (resource)#show
match 'projects/filter' => 'projects#filter', via: [:get, :post], defaults: {format: 'json'}
Expand Down
11 changes: 11 additions & 0 deletions public/listen_to/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<body>
<h1>Client application placeholder</h1>
<p>
This is the page that will be rendered if a client side view needs to be rendered.
</p>
<p>
Replace this page with the <em>baw-client</em> application assets.
</p>
</body>
</html>
113 changes: 111 additions & 2 deletions spec/acceptance/analysis_jobs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def body_params
end

put '/analysis_jobs/:id' do
analysis_jobs_id_param
id_params
let(:id) { 'system' }
let(:raw_post) { body_attributes }
let(:authentication_token) { admin_token }
Expand All @@ -346,6 +346,115 @@ def body_params
expected_json_path: get_json_error_path(:sign_up)})
end

describe 'update special case - retrying the job' do
def set_completed
# low-level modify factory item's state to make this test work
analysis_job.update_column(:overall_status, 'completed')
AnalysisJobsItem.update_all status: :failed
end

# special case - retrying the job
put '/analysis_jobs/:id' do
id_params
parameter :overall_status, 'Analysis Job script id in request body', required: true
let(:id) {
# hack: insert here for correct execution time
set_completed
analysis_job.id
}
let(:raw_post) { {analysis_job: {overall_status: 'processing'}}.to_json }
let(:authentication_token) { admin_token }
standard_request_options(:put, 'UPDATE (retry job, as admin)', :ok, {expected_json_path: 'data/saved_search_id'})
end

# special case - retrying the job
put '/analysis_jobs/:id' do
id_params
parameter :overall_status, 'Analysis Job script id in request body', required: true
let(:id) {
# hack: insert here for correct execution time
set_completed
analysis_job.id
}
let(:raw_post) { {analysis_job: {overall_status: 'processing'}}.to_json }
let(:authentication_token) { writer_token }
standard_request_options(:put, 'UPDATE (retry job, writer)', :ok, {expected_json_path: 'data/saved_search_id'})
end
end

describe 'update special case - pausing the job' do
def set_processing
# low-level modify factory item's state to make this test work
analysis_job.update_column(:overall_status, 'processing')
#AnalysisJobsItem.update_all status: :failed
end

# special case - pausing the job
put '/analysis_jobs/:id' do
id_params
parameter :overall_status, 'Analysis Job script id in request body', required: true
let(:id) {
# hack: insert here for correct execution time
set_processing
analysis_job.id
}
let(:raw_post) { {analysis_job: {overall_status: 'suspended'}}.to_json }
let(:authentication_token) { admin_token }
standard_request_options(:put, 'UPDATE (pause job, as admin)', :ok, {expected_json_path: 'data/saved_search_id'})
end

# special case - pausing the job
put '/analysis_jobs/:id' do
id_params
parameter :overall_status, 'Analysis Job script id in request body', required: true
let(:id) {
# hack: insert here for correct execution time
set_processing
analysis_job.id
}
let(:raw_post) { {analysis_job: {overall_status: 'suspended'}}.to_json }
let(:authentication_token) { writer_token }
standard_request_options(:put, 'UPDATE (pause job, writer)', :ok, {expected_json_path: 'data/saved_search_id'})
end
end


describe 'update special case - resuming the job' do
def set_suspended
# low-level modify factory item's state to make this test work
analysis_job.update_column(:overall_status, 'suspended')
#AnalysisJobsItem.update_all status: :failed
end

# special case - resuming the job
put '/analysis_jobs/:id' do
id_params
parameter :overall_status, 'Analysis Job script id in request body', required: true
let(:id) {
# hack: insert here for correct execution time
set_suspended
analysis_job.id
}
let(:raw_post) { {analysis_job: {overall_status: 'processing'}}.to_json }
let(:authentication_token) { admin_token }
standard_request_options(:put, 'UPDATE (pause job, as admin)', :ok, {expected_json_path: 'data/saved_search_id'})
end

# special case - resuming the job
put '/analysis_jobs/:id' do
id_params
parameter :overall_status, 'Analysis Job script id in request body', required: true
let(:id) {
# hack: insert here for correct execution time
set_suspended
analysis_job.id
}
let(:raw_post) { {analysis_job: {overall_status: 'processing'}}.to_json }
let(:authentication_token) { writer_token }
standard_request_options(:put, 'UPDATE (pause job, writer)', :ok, {expected_json_path: 'data/saved_search_id'})
end
end

################################
# DESTROY
################################
Expand Down Expand Up @@ -421,7 +530,7 @@ def mock_processing_state(opts)
end

delete '/analysis_jobs/:id' do
analysis_jobs_id_param
id_params
let(:id) { 'system' }
let(:authentication_token) { admin_token }
standard_request_options(:delete, 'DESTROY system (as admin)', :method_not_allowed, {
Expand Down

0 comments on commit f9e2036

Please sign in to comment.