Merge pull request #5070 from edx/reruns/error-handling
Course Rerun: include stack trace in errors and Log errors.
This commit is contained in:
@@ -5,6 +5,7 @@ This file contains celery tasks for contentstore views
|
||||
from celery.task import task
|
||||
from django.contrib.auth.models import User
|
||||
import json
|
||||
import logging
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.course_module import CourseFields
|
||||
|
||||
@@ -40,13 +41,15 @@ def rerun_course(source_course_key_string, destination_course_key_string, user_i
|
||||
|
||||
except DuplicateCourseError as exc:
|
||||
# do NOT delete the original course, only update the status
|
||||
CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc)
|
||||
CourseRerunState.objects.failed(course_key=destination_course_key)
|
||||
logging.exception(u'Course Rerun Error')
|
||||
return "duplicate course"
|
||||
|
||||
# catch all exceptions so we can update the state and properly cleanup the course.
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
# update state: Failed
|
||||
CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc)
|
||||
CourseRerunState.objects.failed(course_key=destination_course_key)
|
||||
logging.exception(u'Course Rerun Error')
|
||||
|
||||
try:
|
||||
# cleanup any remnants of the course
|
||||
|
||||
@@ -1699,6 +1699,18 @@ class RerunCourseTest(ContentStoreTestCase):
|
||||
self.user.save()
|
||||
self.post_rerun_request(source_course.id, response_code=403, expect_error=True)
|
||||
|
||||
def test_rerun_error(self):
|
||||
error_message = "Mock Error Message"
|
||||
with mock.patch(
|
||||
'xmodule.modulestore.mixed.MixedModuleStore.clone_course',
|
||||
mock.Mock(side_effect=Exception(error_message))
|
||||
):
|
||||
source_course = CourseFactory.create()
|
||||
destination_course_key = self.post_rerun_request(source_course.id)
|
||||
rerun_state = CourseRerunState.objects.find_first(course_key=destination_course_key)
|
||||
self.assertEquals(rerun_state.state, CourseRerunUIStateManager.State.FAILED)
|
||||
self.assertIn(error_message, rerun_state.message)
|
||||
|
||||
|
||||
class EntryPageTestCase(TestCase):
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Model Managers for Course Actions
|
||||
"""
|
||||
import traceback
|
||||
from django.db import models, transaction
|
||||
|
||||
|
||||
@@ -135,14 +136,14 @@ class CourseRerunUIStateManager(CourseActionUIStateManager):
|
||||
new_state=self.State.SUCCEEDED,
|
||||
)
|
||||
|
||||
def failed(self, course_key, exception):
|
||||
def failed(self, course_key):
|
||||
"""
|
||||
To be called when an existing rerun for the given course has failed with the given exception.
|
||||
To be called within an exception handler when an existing rerun for the given course has failed.
|
||||
"""
|
||||
self.update_state(
|
||||
course_key=course_key,
|
||||
new_state=self.State.FAILED,
|
||||
message=exception.message,
|
||||
message=traceback.format_exc(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -91,12 +91,17 @@ class TestCourseRerunStateManager(TestCase):
|
||||
|
||||
# set state to fail
|
||||
exception = Exception("failure in rerunning")
|
||||
CourseRerunState.objects.failed(course_key=self.course_key, exception=exception)
|
||||
self.expected_rerun_state.update({
|
||||
'state': CourseRerunUIStateManager.State.FAILED,
|
||||
'message': exception.message,
|
||||
})
|
||||
try:
|
||||
raise exception
|
||||
except:
|
||||
CourseRerunState.objects.failed(course_key=self.course_key)
|
||||
|
||||
self.expected_rerun_state.update(
|
||||
{'state': CourseRerunUIStateManager.State.FAILED}
|
||||
)
|
||||
self.expected_rerun_state.pop('message')
|
||||
rerun = self.verify_rerun_state()
|
||||
self.assertIn(exception.message, rerun.message)
|
||||
|
||||
# dismiss ui and verify
|
||||
self.dismiss_ui_and_verify(rerun)
|
||||
|
||||
Reference in New Issue
Block a user