Commit 798f91ca by Stephen Sanchez

Merge pull request #7434 from edx/sanchez/track_internal_request_errors

XCOM-147: Change error handling to report back internal errors.
parents e66409be c01602f0
""" HTTP-related entities. """ """ HTTP-related entities. """
from rest_framework.status import HTTP_503_SERVICE_UNAVAILABLE, HTTP_200_OK from rest_framework.status import HTTP_500_INTERNAL_SERVER_ERROR, HTTP_200_OK
from util.json_request import JsonResponse from util.json_request import JsonResponse
...@@ -13,9 +13,12 @@ class DetailResponse(JsonResponse): ...@@ -13,9 +13,12 @@ class DetailResponse(JsonResponse):
super(DetailResponse, self).__init__(object=data, status=status) super(DetailResponse, self).__init__(object=data, status=status)
class ApiErrorResponse(DetailResponse): class InternalRequestErrorResponse(DetailResponse):
""" Response returned when calls to the E-Commerce API fail or the returned data is invalid. """ """ Response returned when an internal service request fails. """
def __init__(self): def __init__(self, internal_message):
message = 'Call to E-Commerce API failed. Order creation failed.' message = (
super(ApiErrorResponse, self).__init__(message=message, status=HTTP_503_SERVICE_UNAVAILABLE) 'Call to E-Commerce API failed. Internal Service Message: [{internal_message}]'
.format(internal_message=internal_message)
)
super(InternalRequestErrorResponse, self).__init__(message=message, status=HTTP_500_INTERNAL_SERVER_ERROR)
...@@ -48,10 +48,11 @@ class OrdersViewTests(EnrollmentEventTestMixin, EcommerceApiTestMixin, ModuleSto ...@@ -48,10 +48,11 @@ class OrdersViewTests(EnrollmentEventTestMixin, EcommerceApiTestMixin, ModuleSto
actual = json.loads(response.content)['detail'] actual = json.loads(response.content)['detail']
self.assertEqual(actual, expected_msg) self.assertEqual(actual, expected_msg)
def assertValidEcommerceApiErrorResponse(self, response): def assertValidEcommerceInternalRequestErrorResponse(self, response):
""" Asserts the response is a valid response sent when the E-Commerce API is unavailable. """ """ Asserts the response is a valid response sent when the E-Commerce API is unavailable. """
self.assertEqual(response.status_code, 503) self.assertEqual(response.status_code, 500)
self.assertResponseMessage(response, 'Call to E-Commerce API failed. Order creation failed.') actual = json.loads(response.content)['detail']
self.assertIn('Call to E-Commerce API failed', actual)
def assertUserNotEnrolled(self): def assertUserNotEnrolled(self):
""" Asserts that the user is NOT enrolled in the course, and that an enrollment event was NOT fired. """ """ Asserts that the user is NOT enrolled in the course, and that an enrollment event was NOT fired. """
...@@ -112,7 +113,7 @@ class OrdersViewTests(EnrollmentEventTestMixin, EcommerceApiTestMixin, ModuleSto ...@@ -112,7 +113,7 @@ class OrdersViewTests(EnrollmentEventTestMixin, EcommerceApiTestMixin, ModuleSto
with self.mock_create_order(side_effect=TimeoutError): with self.mock_create_order(side_effect=TimeoutError):
response = self._post_to_view() response = self._post_to_view()
self.assertValidEcommerceApiErrorResponse(response) self.assertValidEcommerceInternalRequestErrorResponse(response)
self.assertUserNotEnrolled() self.assertUserNotEnrolled()
def test_ecommerce_api_error(self): def test_ecommerce_api_error(self):
...@@ -122,7 +123,7 @@ class OrdersViewTests(EnrollmentEventTestMixin, EcommerceApiTestMixin, ModuleSto ...@@ -122,7 +123,7 @@ class OrdersViewTests(EnrollmentEventTestMixin, EcommerceApiTestMixin, ModuleSto
with self.mock_create_order(side_effect=ApiError): with self.mock_create_order(side_effect=ApiError):
response = self._post_to_view() response = self._post_to_view()
self.assertValidEcommerceApiErrorResponse(response) self.assertValidEcommerceInternalRequestErrorResponse(response)
self.assertUserNotEnrolled() self.assertUserNotEnrolled()
def _test_successful_ecommerce_api_call(self): def _test_successful_ecommerce_api_call(self):
......
...@@ -10,7 +10,7 @@ from rest_framework.views import APIView ...@@ -10,7 +10,7 @@ from rest_framework.views import APIView
from commerce.api import EcommerceAPI from commerce.api import EcommerceAPI
from commerce.constants import OrderStatus, Messages from commerce.constants import OrderStatus, Messages
from commerce.exceptions import ApiError, InvalidConfigurationError from commerce.exceptions import ApiError, InvalidConfigurationError
from commerce.http import DetailResponse, ApiErrorResponse from commerce.http import DetailResponse, InternalRequestErrorResponse
from course_modes.models import CourseMode from course_modes.models import CourseMode
from courseware import courses from courseware import courses
from enrollment.api import add_enrollment from enrollment.api import add_enrollment
...@@ -120,6 +120,6 @@ class OrdersView(APIView): ...@@ -120,6 +120,6 @@ class OrdersView(APIView):
msg = Messages.ORDER_INCOMPLETE_ENROLLED.format(order_number=order_number) msg = Messages.ORDER_INCOMPLETE_ENROLLED.format(order_number=order_number)
return DetailResponse(msg, status=HTTP_202_ACCEPTED) return DetailResponse(msg, status=HTTP_202_ACCEPTED)
except ApiError: except ApiError as err:
# The API will handle logging of the error. # The API will handle logging of the error.
return ApiErrorResponse() return InternalRequestErrorResponse(err.message)
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