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 celery.task import task
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from xmodule.modulestore.django import modulestore
|
from xmodule.modulestore.django import modulestore
|
||||||
from xmodule.course_module import CourseFields
|
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:
|
except DuplicateCourseError as exc:
|
||||||
# do NOT delete the original course, only update the status
|
# 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"
|
return "duplicate course"
|
||||||
|
|
||||||
# catch all exceptions so we can update the state and properly cleanup the course.
|
# catch all exceptions so we can update the state and properly cleanup the course.
|
||||||
except Exception as exc: # pylint: disable=broad-except
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
# update state: Failed
|
# 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:
|
try:
|
||||||
# cleanup any remnants of the course
|
# cleanup any remnants of the course
|
||||||
|
|||||||
@@ -1699,6 +1699,18 @@ class RerunCourseTest(ContentStoreTestCase):
|
|||||||
self.user.save()
|
self.user.save()
|
||||||
self.post_rerun_request(source_course.id, response_code=403, expect_error=True)
|
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):
|
class EntryPageTestCase(TestCase):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Model Managers for Course Actions
|
Model Managers for Course Actions
|
||||||
"""
|
"""
|
||||||
|
import traceback
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
|
|
||||||
|
|
||||||
@@ -135,14 +136,14 @@ class CourseRerunUIStateManager(CourseActionUIStateManager):
|
|||||||
new_state=self.State.SUCCEEDED,
|
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(
|
self.update_state(
|
||||||
course_key=course_key,
|
course_key=course_key,
|
||||||
new_state=self.State.FAILED,
|
new_state=self.State.FAILED,
|
||||||
message=exception.message,
|
message=traceback.format_exc(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,12 +91,17 @@ class TestCourseRerunStateManager(TestCase):
|
|||||||
|
|
||||||
# set state to fail
|
# set state to fail
|
||||||
exception = Exception("failure in rerunning")
|
exception = Exception("failure in rerunning")
|
||||||
CourseRerunState.objects.failed(course_key=self.course_key, exception=exception)
|
try:
|
||||||
self.expected_rerun_state.update({
|
raise exception
|
||||||
'state': CourseRerunUIStateManager.State.FAILED,
|
except:
|
||||||
'message': exception.message,
|
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()
|
rerun = self.verify_rerun_state()
|
||||||
|
self.assertIn(exception.message, rerun.message)
|
||||||
|
|
||||||
# dismiss ui and verify
|
# dismiss ui and verify
|
||||||
self.dismiss_ui_and_verify(rerun)
|
self.dismiss_ui_and_verify(rerun)
|
||||||
|
|||||||
Reference in New Issue
Block a user