Skip to content

Commit

Permalink
perf: add CompressedCacheResponseMixin to CourseRecommendationsViewSet (
Browse files Browse the repository at this point in the history
  • Loading branch information
AfaqShuaib09 authored Nov 19, 2024
1 parent 6124b84 commit ab17c1b
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 7 deletions.
4 changes: 2 additions & 2 deletions course_discovery/apps/api/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,14 @@ class CompressedCacheResponseMixin():
list_cache_timeout = settings.REST_FRAMEWORK_EXTENSIONS['DEFAULT_CACHE_RESPONSE_TIMEOUT']

@conditional_decorator(
settings.USE_API_CACHING,
lambda: settings.USE_API_CACHING,
compressed_cache_response(key_func=list_cache_key_func, timeout=list_cache_timeout),
)
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)

@conditional_decorator(
settings.USE_API_CACHING,
lambda: settings.USE_API_CACHING,
compressed_cache_response(key_func=object_cache_key_func, timeout=object_cache_timeout),
)
def retrieve(self, request, *args, **kwargs):
Expand Down
14 changes: 11 additions & 3 deletions course_discovery/apps/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,19 @@ def reviewable_data_has_changed(obj, new_key_vals, exempt_fields=None):
return changed_fields


def conditional_decorator(condition, decorator):
def conditional_decorator(condition_getter, decorator):
"""
Util decorator that allows for only using the given decorator arg if the condition passes
Util decorator that applies the given decorator only if the condition passes.
The condition is evaluated at runtime via the `condition_getter` callable, allowing dynamic condition checking.
If callable evaluates to `True`, the provided decorator is applied, otherwise, the function remains unmodified.
"""
return decorator if condition else lambda x: x
def wrapper(func):
def wrapped(*args, **kwargs):
if condition_getter():
return decorator(func)(*args, **kwargs)
return func(*args, **kwargs)
return wrapped
return wrapper


def decode_image_data(image_data):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from django.db.models.functions import Lower
from django.db.models.query import Prefetch
from django.db.models.signals import m2m_changed, pre_save
from django.test import override_settings
from edx_toggles.toggles.testutils import override_waffle_switch
from rest_framework.reverse import reverse
from testfixtures import LogCapture
Expand Down Expand Up @@ -2666,6 +2667,7 @@ def test_html_restricted(self):
self.assertContains(response, 'Invalid HTML received: h1 tag is not allowed', status_code=400)

@responses.activate
@override_settings(USE_API_CACHING=True)
def test_recommendations(self):
courses_sharing_program = CourseFactory.create_batch(2)
ProgramFactory(courses=[self.course, *courses_sharing_program])
Expand All @@ -2684,4 +2686,9 @@ def test_recommendations(self):
with self.assertNumQueries(19, threshold=3):
url = reverse('api:v1:course_recommendations-detail', kwargs={'key': self.course.key})
response = self.client.get(url)
assert response.status_code == 200
assert response.status_code == 200

with self.assertNumQueries(0, threshold=3):
url = reverse('api:v1:course_recommendations-detail', kwargs={'key': self.course.key})
response = self.client.get(url)
assert response.status_code == 200
2 changes: 1 addition & 1 deletion course_discovery/apps/api/v1/views/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ def retrieve(self, request, *args, **kwargs):
return Response(serializer.data)


class CourseRecommendationViewSet(RetrieveModelMixin, viewsets.GenericViewSet):
class CourseRecommendationViewSet(CompressedCacheResponseMixin, RetrieveModelMixin, viewsets.GenericViewSet):
filter_backends = (DjangoFilterBackend, )
lookup_field = 'key'
lookup_value_regex = COURSE_ID_REGEX
Expand Down

0 comments on commit ab17c1b

Please sign in to comment.