diff --git a/backend/coreAdmin/settings.py b/backend/coreAdmin/settings.py index 3f181cdb..0d8b1f66 100644 --- a/backend/coreAdmin/settings.py +++ b/backend/coreAdmin/settings.py @@ -340,6 +340,16 @@ # Skybot da Franca: SKYBOT_SERVER="http://vo.imcce.fr/webservices/skybot/" SKYBOT_SERVER = "http://vo.imcce.fr/webservices/skybot/" +# Memcached +CACHE_HOST = os.environ.get("CACHE_HOST", "memcached") +CACHE_PORT = os.environ.get("CACHE_PORT", 11211) +CACHES = { + "default": { + "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache", + "LOCATION": f"{CACHE_HOST}:{CACHE_PORT}", + } +} + # CELERY_BROKER_URL = os.getenv( # "CELERY_BROKER_URL", "amqp://tno:adminadmin@rabbit:5672/tno_vhost" # ) diff --git a/backend/requirements.txt b/backend/requirements.txt index f54e3a33..993b9c45 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -66,6 +66,7 @@ prometheus-client==0.16.0 psycopg2-binary==2.9.5 pycparser==2.21 pyerfa==2.0.0.1 +pymemcache==4.0.0 pykdtree==1.3.9 pyparsing==3.0.9 pyproj==3.6.1 diff --git a/backend/tno/views/occultation.py b/backend/tno/views/occultation.py index 9720a25d..194e70fb 100644 --- a/backend/tno/views/occultation.py +++ b/backend/tno/views/occultation.py @@ -8,6 +8,7 @@ import humanize from dateutil.relativedelta import relativedelta from django.conf import settings +from django.core.cache import cache from django.db.models import F, FloatField, Q, Value from django.shortcuts import get_object_or_404 from drf_spectacular.utils import extend_schema, inline_serializer @@ -524,12 +525,27 @@ def get_occultation_paths(self, request, pk=None, hash_id=None): @action(detail=False, methods=["get"], permission_classes=(AllowAny,)) def base_dynclass_with_prediction(self, request): """Returns all base_dynclass that have at least one prediction event.""" + # needs to be unique + cache_key = "base_dynclass_with_prediction" + # time in seconds for cache to be valid + cache_time = 86400 # 24h + # returns None if no key-value pair + data = cache.get(cache_key) + + if data is not None: + return Response(data) + queryset = Occultation.objects.order_by("base_dynclass").distinct( "base_dynclass" ) rows = [x.base_dynclass for x in queryset] - return Response(dict({"results": rows, "count": len(rows)})) + result = {"results": rows, "count": len(rows)} + + # Store the data in the cache + cache.set(cache_key, result, cache_time) + + return Response(result) @extend_schema( responses={ @@ -547,10 +563,25 @@ def base_dynclass_with_prediction(self, request): @action(detail=False, methods=["get"], permission_classes=(AllowAny,)) def dynclass_with_prediction(self, request): """Returns all dynclass that have at least one prediction event.""" + # needs to be unique + cache_key = "dynclass_with_prediction" + # time in seconds for cache to be valid + cache_time = 86400 # 24h + # returns None if no key-value pair + data = cache.get(cache_key) + + if data is not None: + return Response(data) + queryset = Occultation.objects.order_by("dynclass").distinct("dynclass") rows = [x.dynclass for x in queryset] - return Response(dict({"results": rows, "count": len(rows)})) + result = {"results": rows, "count": len(rows)} + + # Store the data in the cache + cache.set(cache_key, result, cache_time) + + return Response(result) @extend_schema( responses={ diff --git a/compose/local/docker-compose-template.yml b/compose/local/docker-compose-template.yml index a05bb777..196b6348 100644 --- a/compose/local/docker-compose-template.yml +++ b/compose/local/docker-compose-template.yml @@ -145,6 +145,12 @@ services: mailhog: image: mailhog/mailhog:v1.0.0 + memcached: + image: bitnami/memcached + environment: + - MEMCACHED_CACHE_SIZE=128 + - MEMCACHED_THREADS=4 + - MEMCACHED_MAX_ITEM_SIZE=8388608 # https://medium.com/testing-with-cypress/running-cypress-tests-in-docker-containers-using-different-docker-images-2dee3450881e # cypress: diff --git a/compose/production/docker-compose-template.yml b/compose/production/docker-compose-template.yml index 110d8421..b8bb909d 100644 --- a/compose/production/docker-compose-template.yml +++ b/compose/production/docker-compose-template.yml @@ -93,3 +93,11 @@ services: - .env volumes: - rabbitmq-data:/var/lib/rabbitmq/ + # Memory Cache: Memcached + # Documentation: https://hub.docker.com/r/bitnami/memcached + memcached: + image: bitnami/memcached + environment: + - MEMCACHED_CACHE_SIZE=128 + - MEMCACHED_THREADS=4 + - MEMCACHED_MAX_ITEM_SIZE=8388608 diff --git a/compose/testing/docker-compose-template.yml b/compose/testing/docker-compose-template.yml index 95296f6d..f0e17061 100644 --- a/compose/testing/docker-compose-template.yml +++ b/compose/testing/docker-compose-template.yml @@ -95,3 +95,12 @@ services: RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_DEFAULT_VHOST:-tno_vhost} volumes: - rabbitmq-data:/var/lib/rabbitmq/ + + # Memory Cache: Memcached + # Documentation: https://hub.docker.com/r/bitnami/memcached + memcached: + image: bitnami/memcached + environment: + - MEMCACHED_CACHE_SIZE=128 + - MEMCACHED_THREADS=4 + - MEMCACHED_MAX_ITEM_SIZE=8388608 diff --git a/frontend/src/contexts/PredictionContext.js b/frontend/src/contexts/PredictionContext.js index c282d5d2..e305e211 100644 --- a/frontend/src/contexts/PredictionContext.js +++ b/frontend/src/contexts/PredictionContext.js @@ -16,8 +16,8 @@ export function PredictionEventsProvider({ children }) { filters: { dt_after_local: dayjs(), date_time_after: dayjs().utc().format(), - dt_before_local: null, - date_time_before: null, + dt_before_local: dayjs().add(1, 'month'), + date_time_before: dayjs().utc().add(1, 'month').format(), filterType: '', filterValue: undefined, maginitudeMax: 15,