Repository: tournesol-app/tournesol

Issue:
[extension] optimize: round dates and add cachin to slow Extension's API calls
Some requests to routes for recommendations that look like `/recommendations?before=$NOW-1month` cannot benefit from caching because the `$NOW` parameter would make the cache never hit.

to-do
- [ ] round times used in the extension to the hour or day
- [ ] add hourly caching on the video recommendation route


Discussion:

Resolving patch:
diff --git a/backend/settings/settings.py b/backend/settings/settings.py
--- a/backend/settings/settings.py
+++ b/backend/settings/settings.py
@@ -391,7 +391,13 @@
         "BACKEND": "django.core.cache.backends.db.DatabaseCache",
         "LOCATION": "default_cache_table",
         "OPTIONS": {
-            "MAX_ENTRIES": 3000, # default value is 300
+            # Default value for MAX_ENTRIES is 300.
+            # The heaviest entries in the cache are dynamic page previews or
+            # long lists of videos with their description. These weight in
+            # general between 300kb and 500kb. Another important use of the
+            # cache entries is the rate limiting.
+            # (This comment might be expired, please double check if needed)
+            "MAX_ENTRIES": 100000,
         }
     }
 }
diff --git a/backend/tournesol/views/polls.py b/backend/tournesol/views/polls.py
--- a/backend/tournesol/views/polls.py
+++ b/backend/tournesol/views/polls.py
@@ -3,6 +3,7 @@
 from django.conf import settings
 from django.db.models import Case, F, Sum, When
 from django.shortcuts import get_object_or_404
+from django.utils.decorators import method_decorator
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import (
     OpenApiExample,
@@ -22,6 +23,7 @@
     RecommendationSerializer,
     RecommendationsFilterSerializer,
 )
+from tournesol.utils.cache import cache_page_no_i18n
 from tournesol.utils.constants import CRITERIA_DEFAULT_WEIGHT, MEHESTAN_MAX_SCALED_SCORE
 from tournesol.views import PollScopedViewMixin
 
@@ -262,6 +264,10 @@ class PollsRecommendationsView(PollRecommendationsBaseAPIView):
     queryset = Entity.objects.none()
     serializer_class = RecommendationSerializer
 
+    @method_decorator(cache_page_no_i18n(60 * 10))  # 10 minutes cache
+    def list(self, *args, **kwargs):
+        return super().list(self, *args, **kwargs)
+
     def annotate_and_prefetch_scores(self, queryset, request, poll: Poll):
         raw_score_mode = request.query_params.get("score_mode", ScoreMode.DEFAULT)
         try:


Test patch:
diff --git a/backend/tournesol/tests/test_text_search.py b/backend/tournesol/tests/test_text_search.py
--- a/backend/tournesol/tests/test_text_search.py
+++ b/backend/tournesol/tests/test_text_search.py
@@ -1,5 +1,6 @@
 from urllib.parse import urlencode
 
+from django.core.cache import cache
 from django.test import TestCase
 from rest_framework import status
 from rest_framework.test import APIClient
@@ -249,7 +250,8 @@ def test_stop_words(self):
         self.assertEqual(response.data["count"], self.setup_results_count)
 
         self._create_rated_entity(field1="cake")
-
+        
+        cache.clear()
         response = self.client.get(
             self._make_url(query),
             format="json"
@@ -276,7 +278,8 @@ def test_stop_words_french(self):
         self.assertEqual(response.data["count"], 0)
 
         self._create_rated_entity(field1="oignon", language="fr")
-
+        
+        cache.clear()
         response = self.client.get(
             self._make_url(query, "fr"),
             format="json"