Commit 896bc1c8 by stephensanchez

Adding caching to the course details endpoint for the Enrollment API.

parent fcd7736d
...@@ -5,6 +5,7 @@ course level, such as available course modes. ...@@ -5,6 +5,7 @@ course level, such as available course modes.
""" """
from django.utils import importlib from django.utils import importlib
import logging import logging
from django.core.cache import cache
from django.conf import settings from django.conf import settings
from enrollment import errors from enrollment import errors
...@@ -250,7 +251,31 @@ def get_course_enrollment_details(course_id): ...@@ -250,7 +251,31 @@ def get_course_enrollment_details(course_id):
} }
""" """
return _data_api().get_course_enrollment_info(course_id) cache_key = u"enrollment.course.details.{course_id}".format(course_id=course_id)
cached_enrollment_data = None
try:
cached_enrollment_data = cache.get(cache_key)
except Exception:
# The cache backend could raise an exception (for example, memcache keys that contain spaces)
log.exception(u"Error occurred while retrieving course enrollment details from the cache")
if cached_enrollment_data:
log.info(u"Get enrollment data for course %s (cached)", course_id)
return cached_enrollment_data
course_enrollment_details = _data_api().get_course_enrollment_info(course_id)
try:
cache_time_out = getattr(settings, 'ENROLLMENT_COURSE_DETAILS_CACHE_TIMEOUT', 60)
cache.set(cache_key, course_enrollment_details, cache_time_out)
except Exception:
# Catch any unexpected errors during caching.
log.exception(u"Error occurred while caching course enrollment details for course %s", course_id)
raise errors.CourseEnrollmentError(u"An unexpected error occurred while retrieving course enrollment details.")
log.info(u"Get enrollment data for course %s", course_id)
return course_enrollment_details
def _validate_course_mode(course_id, mode): def _validate_course_mode(course_id, mode):
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Tests for student enrollment. Tests for student enrollment.
""" """
import ddt import ddt
from django.core.cache import cache
from nose.tools import raises from nose.tools import raises
import unittest import unittest
from django.test import TestCase from django.test import TestCase
...@@ -24,6 +25,7 @@ class EnrollmentTest(TestCase): ...@@ -24,6 +25,7 @@ class EnrollmentTest(TestCase):
def setUp(self): def setUp(self):
fake_data_api.reset() fake_data_api.reset()
cache.clear()
@ddt.data( @ddt.data(
# Default (no course modes in the database) # Default (no course modes in the database)
...@@ -125,7 +127,7 @@ class EnrollmentTest(TestCase): ...@@ -125,7 +127,7 @@ class EnrollmentTest(TestCase):
) )
def test_update_enrollment(self): def test_update_enrollment(self):
# Add a fake course enrollment information to the fake data API # Add fake course enrollment information to the fake data API
fake_data_api.add_course(self.COURSE_ID, course_modes=['honor', 'verified', 'audit']) fake_data_api.add_course(self.COURSE_ID, course_modes=['honor', 'verified', 'audit'])
# Enroll in the course and verify the URL we get sent to # Enroll in the course and verify the URL we get sent to
result = api.add_enrollment(self.USERNAME, self.COURSE_ID, mode='audit') result = api.add_enrollment(self.USERNAME, self.COURSE_ID, mode='audit')
...@@ -150,3 +152,18 @@ class EnrollmentTest(TestCase): ...@@ -150,3 +152,18 @@ class EnrollmentTest(TestCase):
def test_data_api_config_error(self): def test_data_api_config_error(self):
# Enroll in the course and verify the URL we get sent to # Enroll in the course and verify the URL we get sent to
api.add_enrollment(self.USERNAME, self.COURSE_ID, mode='audit') api.add_enrollment(self.USERNAME, self.COURSE_ID, mode='audit')
def test_caching(self):
# Add fake course enrollment information to the fake data API
fake_data_api.add_course(self.COURSE_ID, course_modes=['honor', 'verified', 'audit'])
# Hit the fake data API.
details = api.get_course_enrollment_details(self.COURSE_ID)
# Reset the fake data API, should rely on the cache.
fake_data_api.reset()
cached_details = api.get_course_enrollment_details(self.COURSE_ID)
# The data matches
self.assertEqual(len(details['course_modes']), 3)
self.assertEqual(details, cached_details)
...@@ -484,6 +484,9 @@ INVOICE_PAYMENT_INSTRUCTIONS = ENV_TOKENS.get('INVOICE_PAYMENT_INSTRUCTIONS', IN ...@@ -484,6 +484,9 @@ INVOICE_PAYMENT_INSTRUCTIONS = ENV_TOKENS.get('INVOICE_PAYMENT_INSTRUCTIONS', IN
API_DATE_FORMAT = '%Y-%m-%d' API_DATE_FORMAT = '%Y-%m-%d'
API_DATE_FORMAT = ENV_TOKENS.get('API_DATE_FORMAT', API_DATE_FORMAT) API_DATE_FORMAT = ENV_TOKENS.get('API_DATE_FORMAT', API_DATE_FORMAT)
# Enrollment API Cache Timeout
ENROLLMENT_COURSE_DETAILS_CACHE_TIMEOUT = ENV_TOKENS.get('ENROLLMENT_COURSE_DETAILS_CACHE_TIMEOUT', 60)
# PDF RECEIPT/INVOICE OVERRIDES # PDF RECEIPT/INVOICE OVERRIDES
PDF_RECEIPT_TAX_ID = ENV_TOKENS.get('PDF_RECEIPT_TAX_ID', PDF_RECEIPT_TAX_ID) PDF_RECEIPT_TAX_ID = ENV_TOKENS.get('PDF_RECEIPT_TAX_ID', PDF_RECEIPT_TAX_ID)
PDF_RECEIPT_FOOTER_TEXT = ENV_TOKENS.get('PDF_RECEIPT_FOOTER_TEXT', PDF_RECEIPT_FOOTER_TEXT) PDF_RECEIPT_FOOTER_TEXT = ENV_TOKENS.get('PDF_RECEIPT_FOOTER_TEXT', PDF_RECEIPT_FOOTER_TEXT)
......
...@@ -1990,6 +1990,9 @@ COURSE_ABOUT_VISIBILITY_PERMISSION = 'see_exists' ...@@ -1990,6 +1990,9 @@ COURSE_ABOUT_VISIBILITY_PERMISSION = 'see_exists'
#date format the api will be formatting the datetime values #date format the api will be formatting the datetime values
API_DATE_FORMAT = '%Y-%m-%d' API_DATE_FORMAT = '%Y-%m-%d'
# Enrollment API Cache Timeout
ENROLLMENT_COURSE_DETAILS_CACHE_TIMEOUT = 60
# for Student Notes we would like to avoid too frequent token refreshes (default is 30 seconds) # for Student Notes we would like to avoid too frequent token refreshes (default is 30 seconds)
if FEATURES['ENABLE_EDXNOTES']: if FEATURES['ENABLE_EDXNOTES']:
OAUTH_ID_TOKEN_EXPIRATION = 60 * 60 OAUTH_ID_TOKEN_EXPIRATION = 60 * 60
......
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