Commit 08a0c639 by Nimisha Asthagiri

Merge pull request #5070 from edx/reruns/error-handling

Course Rerun: include stack trace in errors and Log errors.
parents 97527266 bdd91dae
...@@ -5,6 +5,7 @@ This file contains celery tasks for contentstore views ...@@ -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 ...@@ -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): ...@@ -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):
""" """
......
""" """
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): ...@@ -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): ...@@ -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)
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