Commit d1da0445 by noraiz-anwar

Throw error if messaging queue is not available

parent 3e7243ea
......@@ -25,7 +25,26 @@ log = logging.getLogger(__name__)
class AlreadyRunningError(Exception):
"""Exception indicating that a background task is already running"""
pass
message = _('Requested task is already running')
def __init__(self, message=None):
if not message:
message = self.message
super(AlreadyRunningError, self).__init__(message)
class QueueConnectionError(Exception):
"""
Exception indicating that celery task was not created successfully.
"""
message = _('Error occured. Please try again later.')
def __init__(self, message=None):
if not message:
message = self.message
super(QueueConnectionError, self).__init__(message)
def _task_is_running(course_id, task_type, task_key):
......@@ -57,7 +76,8 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester):
if _task_is_running(course_id, task_type, task_key):
log.warning("Duplicate task found for task_type %s and task_key %s", task_type, task_key)
raise AlreadyRunningError("requested task is already running")
error_message = generate_already_running_error_message(task_type)
raise AlreadyRunningError(error_message)
try:
most_recent_id = InstructorTask.objects.latest('id').id
......@@ -75,6 +95,37 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester):
return InstructorTask.create(course_id, task_type, task_key, task_input, requester)
def generate_already_running_error_message(task_type):
"""
Returns already running error message for given task type.
"""
message = ''
report_types = {
'grade_problems': _('problem grade'),
'problem_responses_csv': _('problem responses'),
'profile_info_csv': _('enrolled learner profile'),
'may_enroll_info_csv': _('enrollment'),
'detailed_enrollment_report': _('detailed enrollment'),
'exec_summary_report': _('executive summary'),
'course_survey_report': _('survey'),
'proctored_exam_results_report': _('proctored exam results'),
'export_ora2_data': _('ORA data'),
'grade_course': _('grade'),
}
if report_types.get(task_type):
message = _(
"The {report_type} report is being created. "
"To view the status of the report, see Pending Tasks below. "
"You will be able to download the report when it is complete."
).format(report_type=report_types.get(task_type))
return message
def _get_xmodule_instance_args(request, task_id):
"""
Calculate parameters needed for instantiating xmodule instances.
......@@ -190,6 +241,27 @@ def _update_instructor_task(instructor_task, task_result):
instructor_task.save()
def _update_instructor_task_state(instructor_task, task_state, message=None):
"""
Update state and output of InstructorTask object.
"""
instructor_task.task_state = task_state
if message:
instructor_task.task_output = message
instructor_task.save()
def _handle_instructor_task_failure(instructor_task, error):
"""
Do required operations if task creation was not complete.
"""
log.info("instructor task (%s) failed, result: %s", instructor_task.task_id, error.message)
_update_instructor_task_state(instructor_task, FAILURE, error.message)
raise QueueConnectionError()
def get_updated_instructor_task(task_id):
"""
Returns InstructorTask object corresponding to a given `task_id`.
......@@ -365,6 +437,10 @@ def submit_task(request, task_type, task_class, course_key, task_input, task_key
task_id = instructor_task.task_id
task_args = [instructor_task.id, _get_xmodule_instance_args(request, task_id)]
task_class.apply_async(task_args, task_id=task_id)
try:
task_class.apply_async(task_args, task_id=task_id)
except Exception as error:
_handle_instructor_task_failure(instructor_task, error)
return instructor_task
......@@ -32,7 +32,7 @@ from lms.djangoapps.instructor_task.api import (
submit_reset_problem_attempts_for_all_students,
submit_reset_problem_attempts_in_entrance_exam
)
from lms.djangoapps.instructor_task.api_helper import AlreadyRunningError
from lms.djangoapps.instructor_task.api_helper import AlreadyRunningError, QueueConnectionError
from lms.djangoapps.instructor_task.models import PROGRESS, InstructorTask
from lms.djangoapps.instructor_task.tasks import export_ora2_data
from lms.djangoapps.instructor_task.tests.test_base import (
......@@ -43,6 +43,7 @@ from lms.djangoapps.instructor_task.tests.test_base import (
TestReportMixin
)
from xmodule.modulestore.exceptions import ItemNotFoundError
from celery.states import FAILURE
class InstructorTaskReportTest(InstructorTaskTestCase):
......@@ -164,15 +165,31 @@ class InstructorTaskModuleSubmitTest(InstructorTaskModuleTestCase):
)
@ddt.unpack
def test_submit_task(self, task_function, expected_task_type, params=None):
"""
Tests submission of instructor task.
"""
if params is None:
params = {}
if params.get('student'):
params['student'] = self.student
# tests submit, and then tests a second identical submission.
problem_url_name = 'H1P1'
self.define_option_problem(problem_url_name)
location = InstructorTaskModuleTestCase.problem_location(problem_url_name)
# unsuccessful submission, exception raised while submitting.
with patch('lms.djangoapps.instructor_task.tasks_base.BaseInstructorTask.apply_async') as apply_async:
error = Exception()
apply_async.side_effect = error
with self.assertRaises(QueueConnectionError):
instructor_task = task_function(self.create_task_request(self.instructor), location, **params)
most_recent_task = InstructorTask.objects.latest('id')
self.assertEquals(most_recent_task.task_state, FAILURE)
# successful submission
instructor_task = task_function(self.create_task_request(self.instructor), location, **params)
self.assertEquals(instructor_task.task_type, expected_task_type)
......
......@@ -122,16 +122,18 @@
});
this.$proctored_exam_csv_btn.click(function() {
var url = dataDownloadObj.$proctored_exam_csv_btn.data('endpoint');
var errorMessage = gettext('Error generating proctored exam results. Please try again.');
return $.ajax({
type: 'POST',
dataType: 'json',
url: url,
error: function() {
error: function(error) {
if (error.responseText) {
errorMessage = JSON.parse(error.responseText);
}
dataDownloadObj.clear_display();
dataDownloadObj.$reports_request_response_error.text(
gettext('Error generating proctored exam results. Please try again.')
);
return $('.msg-error').css({
dataDownloadObj.$reports_request_response_error.text(errorMessage);
return dataDownloadObj.$reports_request_response_error.css({
display: 'block'
});
},
......@@ -146,16 +148,18 @@
});
this.$survey_results_csv_btn.click(function() {
var url = dataDownloadObj.$survey_results_csv_btn.data('endpoint');
var errorMessage = gettext('Error generating survey results. Please try again.');
return $.ajax({
type: 'POST',
dataType: 'json',
url: url,
error: function() {
error: function(error) {
if (error.responseText) {
errorMessage = JSON.parse(error.responseText);
}
dataDownloadObj.clear_display();
dataDownloadObj.$reports_request_response_error.text(
gettext('Error generating survey results. Please try again.')
);
return $('.msg-error').css({
dataDownloadObj.$reports_request_response_error.text(errorMessage);
return dataDownloadObj.$reports_request_response_error.css({
display: 'block'
});
},
......@@ -170,16 +174,18 @@
});
this.$list_studs_csv_btn.click(function() {
var url = dataDownloadObj.$list_studs_csv_btn.data('endpoint') + '/csv';
var errorMessage = gettext('Error generating student profile information. Please try again.');
dataDownloadObj.clear_display();
return $.ajax({
type: 'POST',
dataType: 'json',
url: url,
error: function() {
dataDownloadObj.$reports_request_response_error.text(
gettext('Error generating student profile information. Please try again.')
);
return $('.msg-error').css({
error: function(error) {
if (error.responseText) {
errorMessage = JSON.parse(error.responseText);
}
dataDownloadObj.$reports_request_response_error.text(errorMessage);
return dataDownloadObj.$reports_request_response_error.css({
display: 'block'
});
},
......@@ -201,9 +207,13 @@
url: url,
error: function() {
dataDownloadObj.clear_display();
return dataDownloadObj.$download_request_response_error.text(
dataDownloadObj.$download_request_response_error.text(
gettext('Error getting student list.')
);
return dataDownloadObj.$download_request_response_error.css({
display: 'block'
});
},
success: function(data) {
var $tablePlaceholder, columns, feature, gridData, options;
......@@ -251,7 +261,7 @@
dataDownloadObj.$reports_request_response_error.text(
JSON.parse(error.responseText)
);
return $('.msg-error').css({
return dataDownloadObj.$reports_request_response_error.css({
display: 'block'
});
},
......@@ -265,16 +275,18 @@
});
this.$list_may_enroll_csv_btn.click(function() {
var url = dataDownloadObj.$list_may_enroll_csv_btn.data('endpoint');
var errorMessage = gettext('Error generating list of students who may enroll. Please try again.');
dataDownloadObj.clear_display();
return $.ajax({
type: 'POST',
dataType: 'json',
url: url,
error: function() {
dataDownloadObj.$reports_request_response_error.text(
gettext('Error generating list of students who may enroll. Please try again.')
);
return $('.msg-error').css({
error: function(error) {
if (error.responseText) {
errorMessage = JSON.parse(error.responseText);
}
dataDownloadObj.$reports_request_response_error.text(errorMessage);
return dataDownloadObj.$reports_request_response_error.css({
display: 'block'
});
},
......@@ -294,9 +306,12 @@
url: url,
error: function() {
dataDownloadObj.clear_display();
return dataDownloadObj.$download_request_response_error.text(
dataDownloadObj.$download_request_response_error.text(
gettext('Error retrieving grading configuration.')
);
return dataDownloadObj.$download_request_response_error.css({
display: 'block'
});
},
success: function(data) {
dataDownloadObj.clear_display();
......@@ -307,29 +322,27 @@
});
this.$async_report_btn.click(function(e) {
var url = $(e.target).data('endpoint');
var errorMessage = '';
dataDownloadObj.clear_display();
return $.ajax({
type: 'POST',
dataType: 'json',
url: url,
error: statusAjaxError(function() {
if (e.target.name === 'calculate-grades-csv') {
dataDownloadObj.$grades_request_response_error.text(
gettext('Error generating grades. Please try again.')
);
error: function(error) {
if (error.responseText) {
errorMessage = JSON.parse(error.responseText);
} else if (e.target.name === 'calculate-grades-csv') {
errorMessage = gettext('Error generating grades. Please try again.');
} else if (e.target.name === 'problem-grade-report') {
dataDownloadObj.$grades_request_response_error.text(
gettext('Error generating problem grade report. Please try again.')
);
errorMessage = gettext('Error generating problem grade report. Please try again.');
} else if (e.target.name === 'export-ora2-data') {
dataDownloadObj.$grades_request_response_error.text(
gettext('Error generating ORA data report. Please try again.')
);
errorMessage = gettext('Error generating ORA data report. Please try again.');
}
return $('.msg-error').css({
dataDownloadObj.$reports_request_response_error.text(errorMessage);
return dataDownloadObj.$reports_request_response_error.css({
display: 'block'
});
}),
},
success: function(data) {
dataDownloadObj.$reports_request_response.text(data.status);
return $('.msg-confirm').css({
......
......@@ -96,7 +96,7 @@ define([
error_msg: 'Failed to reset attempts for user.'
};
StaffDebug.doInstructorDashAction(action);
AjaxHelpers.respondWithError(requests);
AjaxHelpers.respondWithTextError(requests);
expect($('#idash_msg').text()).toBe('Failed to reset attempts for user. ');
$('#result_' + locationName).remove();
});
......
......@@ -54,12 +54,12 @@ var StaffDebug = (function() {
try {
responseJSON = $.parseJSON(request.responseText);
} catch (e) {
responseJSON = {error: gettext('Unknown Error Occurred.')};
responseJSON = 'Unknown Error Occurred.';
}
var text = _.template('{error_msg} {error}', {interpolate: /\{(.+?)\}/g})(
{
error_msg: action.error_msg,
error: responseJSON.error
error: gettext(responseJSON)
}
);
var html = _.template('<p id="idash_msg" class="error">{text}</p>', {interpolate: /\{(.+?)\}/g})(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment