Commit b21d6064 by Usman Khalid Committed by Usman Khalid

If unable to send submission/feedback to xqueue return an error instead of silently failing.

ORA-197
parent a7d3a23f
...@@ -196,20 +196,25 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -196,20 +196,25 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'student_info': json.dumps(student_info), 'student_info': json.dumps(student_info),
} }
(error, msg) = qinterface.send_to_queue( error, error_message = qinterface.send_to_queue(
header=xheader, header=xheader,
body=json.dumps(contents) body=json.dumps(contents)
) )
# Convert error to a success value # Convert error to a success value
success = True success = True
message = "Successfully saved your feedback."
if error: if error:
success = False success = False
message = "Unable to save your feedback. Please try again later."
self.child_state = self.DONE log.error("Unable to send feedback to grader. location: {0}, error_message: {1}".format(
self.location_string, error_message
))
else:
self.child_state = self.DONE
# This is a student_facing_message # This is a student_facing_message
return {'success': success, 'msg': "Successfully submitted your feedback."} return {'success': success, 'msg': message}
def send_to_grader(self, submission, system): def send_to_grader(self, submission, system):
""" """
...@@ -257,7 +262,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -257,7 +262,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
}) })
# Submit request. When successful, 'msg' is the prior length of the queue # Submit request. When successful, 'msg' is the prior length of the queue
qinterface.send_to_queue( error, error_message = qinterface.send_to_queue(
header=xheader, header=xheader,
body=json.dumps(contents) body=json.dumps(contents)
) )
...@@ -267,7 +272,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -267,7 +272,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'key': queuekey, 'key': queuekey,
'time': qtime, 'time': qtime,
} }
return True
success = True
message = "Successfully saved your submission."
if error:
success = False
message = 'Unable to send your submission to grader. Please try again later.'
log.error("Unable to submit to grader. location: {0}, error_message: {1}".format(
self.location_string, error_message
))
return (success, message)
def _update_score(self, score_msg, queuekey, system): def _update_score(self, score_msg, queuekey, system):
""" """
...@@ -671,17 +686,24 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -671,17 +686,24 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
if self.child_state != self.INITIAL: if self.child_state != self.INITIAL:
return self.out_of_sync_error(data) return self.out_of_sync_error(data)
message = "Successfully saved your submission."
# add new history element with answer and empty score and hint. # add new history element with answer and empty score and hint.
success, error_message, data = self.append_file_link_to_student_answer(data) success, error_message, data = self.append_file_link_to_student_answer(data)
if success: if not success:
message = error_message
else:
data['student_answer'] = OpenEndedModule.sanitize_html(data['student_answer']) data['student_answer'] = OpenEndedModule.sanitize_html(data['student_answer'])
self.new_history_entry(data['student_answer']) success, error_message = self.send_to_grader(data['student_answer'], system)
self.send_to_grader(data['student_answer'], system) if not success:
self.change_state(self.ASSESSING) message = error_message
else:
self.new_history_entry(data['student_answer'])
self.change_state(self.ASSESSING)
return { return {
'success': success, 'success': success,
'error': error_message, 'error': message,
'student_response': data['student_answer'].replace("\n", "<br/>") 'student_response': data['student_answer'].replace("\n", "<br/>")
} }
......
...@@ -254,7 +254,7 @@ class OpenEndedModuleTest(unittest.TestCase): ...@@ -254,7 +254,7 @@ class OpenEndedModuleTest(unittest.TestCase):
self.test_system.open_ended_grading_interface = None self.test_system.open_ended_grading_interface = None
self.test_system.location = self.location self.test_system.location = self.location
self.mock_xqueue = MagicMock() self.mock_xqueue = MagicMock()
self.mock_xqueue.send_to_queue.return_value = (None, "Message") self.mock_xqueue.send_to_queue.return_value = (0, "Queued")
def constructed_callback(dispatch="score_update"): def constructed_callback(dispatch="score_update"):
return dispatch return dispatch
...@@ -290,7 +290,32 @@ class OpenEndedModuleTest(unittest.TestCase): ...@@ -290,7 +290,32 @@ class OpenEndedModuleTest(unittest.TestCase):
self.mock_xqueue.send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY) self.mock_xqueue.send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY)
state = json.loads(self.openendedmodule.get_instance_state()) state = json.loads(self.openendedmodule.get_instance_state())
self.assertIsNotNone(state['child_state'], OpenEndedModule.DONE) self.assertEqual(state['child_state'], OpenEndedModule.DONE)
def test_message_post_fail(self):
"""Test message_post() if unable to send feedback to xqueue."""
get = {'feedback': 'feedback text',
'submission_id': '1',
'grader_id': '1',
'score': 3}
qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)
student_info = {'anonymous_student_id': self.test_system.anonymous_student_id,
'submission_time': qtime}
contents = {
'feedback': get['feedback'],
'submission_id': int(get['submission_id']),
'grader_id': int(get['grader_id']),
'score': get['score'],
'student_info': json.dumps(student_info)
}
self.mock_xqueue.send_to_queue.return_value = (1, "Not Queued")
result = self.openendedmodule.message_post(get, self.test_system)
self.assertFalse(result['success'])
state = json.loads(self.openendedmodule.get_instance_state())
self.assertNotEqual(state['child_state'], OpenEndedModule.DONE)
# Disabled 1/27/14 due to flakiness in master # Disabled 1/27/14 due to flakiness in master
# Should not be comparing the submission time to the current time! # Should not be comparing the submission time to the current time!
...@@ -306,10 +331,41 @@ class OpenEndedModuleTest(unittest.TestCase): ...@@ -306,10 +331,41 @@ class OpenEndedModuleTest(unittest.TestCase):
'student_response': submission, 'student_response': submission,
'max_score': self.max_score 'max_score': self.max_score
}) })
result = self.openendedmodule.send_to_grader(submission, self.test_system) result, __ = self.openendedmodule.send_to_grader(submission, self.test_system)
self.assertTrue(result) self.assertTrue(result)
self.mock_xqueue.send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY) self.mock_xqueue.send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY)
def test_send_to_grader_fail(self):
"""Test send_to_grader() if unable to send submission to xqueue."""
submission = "This is a student submission"
qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)
student_info = {'anonymous_student_id': self.test_system.anonymous_student_id,
'submission_time': qtime}
contents = self.openendedmodule.payload.copy()
contents.update({
'student_info': json.dumps(student_info),
'student_response': submission,
'max_score': self.max_score
})
self.mock_xqueue.send_to_queue.return_value = (1, "Not Queued")
result, __ = self.openendedmodule.send_to_grader(submission, self.test_system)
self.assertFalse(result)
def test_save_answer_fail(self):
"""Test save_answer() if unable to send submission to grader."""
submission = "This is a student submission"
self.openendedmodule.send_to_grader = Mock(return_value=(False, "Failed"))
response = self.openendedmodule.save_answer(
{"student_answer": submission},
get_test_system()
)
self.assertFalse(response['success'])
self.assertNotEqual(self.openendedmodule.latest_answer(), submission)
state = json.loads(self.openendedmodule.get_instance_state())
self.assertEqual(state['child_state'], OpenEndedModule.INITIAL)
def update_score_single(self): def update_score_single(self):
self.openendedmodule.new_history_entry("New Entry") self.openendedmodule.new_history_entry("New Entry")
get = {'queuekey': "abcd", get = {'queuekey': "abcd",
...@@ -384,7 +440,7 @@ class OpenEndedModuleTest(unittest.TestCase): ...@@ -384,7 +440,7 @@ class OpenEndedModuleTest(unittest.TestCase):
self.assertEqual(test_module.get_display_answer(), saved_response) self.assertEqual(test_module.get_display_answer(), saved_response)
# Mock out the send_to_grader function so it doesn't try to connect to the xqueue. # Mock out the send_to_grader function so it doesn't try to connect to the xqueue.
test_module.send_to_grader = Mock(return_value=True) test_module.send_to_grader = Mock(return_value=(True, "Success"))
# Submit a student response to the question. # Submit a student response to the question.
test_module.handle_ajax( test_module.handle_ajax(
"save_answer", "save_answer",
...@@ -937,7 +993,7 @@ class OpenEndedModuleXmlTest(unittest.TestCase, DummyModulestore): ...@@ -937,7 +993,7 @@ class OpenEndedModuleXmlTest(unittest.TestCase, DummyModulestore):
test_system = get_test_system() test_system = get_test_system()
test_system.open_ended_grading_interface = None test_system.open_ended_grading_interface = None
test_system.xqueue['interface'] = Mock( test_system.xqueue['interface'] = Mock(
send_to_queue=Mock(side_effect=[1, "queued"]) send_to_queue=Mock(return_value=(0, "Queued"))
) )
return test_system return test_system
...@@ -1098,7 +1154,7 @@ class OpenEndedModuleXmlAttemptTest(unittest.TestCase, DummyModulestore): ...@@ -1098,7 +1154,7 @@ class OpenEndedModuleXmlAttemptTest(unittest.TestCase, DummyModulestore):
test_system = get_test_system() test_system = get_test_system()
test_system.open_ended_grading_interface = None test_system.open_ended_grading_interface = None
test_system.xqueue['interface'] = Mock( test_system.xqueue['interface'] = Mock(
send_to_queue=Mock(side_effect=[1, "queued"]) send_to_queue=Mock(return_value=(0, "Queued"))
) )
return test_system return test_system
...@@ -1172,7 +1228,7 @@ class OpenEndedModuleXmlImageUploadTest(unittest.TestCase, DummyModulestore): ...@@ -1172,7 +1228,7 @@ class OpenEndedModuleXmlImageUploadTest(unittest.TestCase, DummyModulestore):
test_system.open_ended_grading_interface = None test_system.open_ended_grading_interface = None
test_system.s3_interface = test_util_open_ended.S3_INTERFACE test_system.s3_interface = test_util_open_ended.S3_INTERFACE
test_system.xqueue['interface'] = Mock( test_system.xqueue['interface'] = Mock(
send_to_queue=Mock(side_effect=[1, "queued"]) send_to_queue=Mock(return_value=(0, "Queued"))
) )
return test_system return test_system
......
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