From 483ca6fefcd77d72bceb9b77aaf0efe5af59a5e7 Mon Sep 17 00:00:00 2001 From: Ptitloup Date: Tue, 3 Oct 2023 10:54:20 +0200 Subject: [PATCH] [DONE] Use cache to store video data (#969) * Use cache to store video data - get it in context - create command to store video data * change name of video context processor * add some pydoc * update cache timeout to 600 seconds - use DRY and call context cache video data instead of repeat code * use delete many to clear cache --- pod/settings.py | 2 +- pod/video/context_processors.py | 74 +++++++++++-------- .../management/commands/cache_video_data.py | 28 +++++++ 3 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 pod/video/management/commands/cache_video_data.py diff --git a/pod/settings.py b/pod/settings.py index 39f0867b10..00a1179592 100644 --- a/pod/settings.py +++ b/pod/settings.py @@ -117,7 +117,7 @@ # Local contexts "pod.main.context_processors.context_settings", "pod.main.context_processors.context_footer", - "pod.video.context_processors.context_navbar", + "pod.video.context_processors.context_video_data", "pod.video.context_processors.context_video_settings", "pod.authentication.context_processors.context_authentication_settings", "pod.recorder.context_processors.context_recorder_settings", diff --git a/pod/video/context_processors.py b/pod/video/context_processors.py index f76f2e337b..c0bc18a2b4 100644 --- a/pod/video/context_processors.py +++ b/pod/video/context_processors.py @@ -10,6 +10,7 @@ from django.db.models import OuterRef from datetime import timedelta +from django.core.cache import cache from django.contrib.sites.shortcuts import get_current_site from pod.video_encode_transcript.models import EncodingVideo from pod.video_encode_transcript.models import PlaylistVideo @@ -19,7 +20,7 @@ HIDE_USER_FILTER = getattr(django_settings, "HIDE_USER_FILTER", False) OEMBED = getattr(django_settings, "OEMBED", False) USE_STATS_VIEW = getattr(django_settings, "USE_STATS_VIEW", False) - +CACHE_VIDEO_DEFAULT_TIMEOUT = getattr(django_settings, "CACHE_VIDEO_DEFAULT_TIMEOUT", 600) __AVAILABLE_VIDEO_FILTER__ = { "encoding_in_progress": False, "is_draft": False, @@ -78,37 +79,50 @@ def context_video_settings(request): return new_settings -def context_navbar(request): - types = ( - Type.objects.filter( - sites=get_current_site(request), - video__is_draft=False, - video__sites=get_current_site(request), +def context_video_data(request): + """Get video data in cache, if not, create and add it in cache.""" + types = cache.get('TYPES') + if types is None: + types = ( + Type.objects.filter( + sites=get_current_site(request), + video__is_draft=False, + video__sites=get_current_site(request), + ) + .distinct() + .annotate(video_count=Count("video", distinct=True)) ) - .distinct() - .annotate(video_count=Count("video", distinct=True)) - ) - - disciplines = ( - Discipline.objects.filter( - site=get_current_site(request), - video__is_draft=False, - video__sites=get_current_site(request), + cache.set("TYPES", types, timeout=CACHE_VIDEO_DEFAULT_TIMEOUT) + + disciplines = cache.get('DISCIPLINES') + if disciplines is None: + disciplines = ( + Discipline.objects.filter( + site=get_current_site(request), + video__is_draft=False, + video__sites=get_current_site(request), + ) + .distinct() + .annotate(video_count=Count("video", distinct=True)) ) - .distinct() - .annotate(video_count=Count("video", distinct=True)) - ) - - v_filter = get_available_videos_filter(request) - - aggregate_videos = v_filter.aggregate(duration=Sum("duration"), number=Count("id")) - - VIDEOS_COUNT = aggregate_videos["number"] - VIDEOS_DURATION = ( - str(timedelta(seconds=aggregate_videos["duration"])) - if aggregate_videos["duration"] - else 0 - ) + cache.set("DISCIPLINES", disciplines, timeout=CACHE_VIDEO_DEFAULT_TIMEOUT) + + VIDEOS_COUNT = cache.get('VIDEOS_COUNT') + VIDEOS_DURATION = cache.get('VIDEOS_DURATION') + if VIDEOS_COUNT is None: + v_filter = get_available_videos_filter(request) + aggregate_videos = v_filter.aggregate( + duration=Sum("duration"), + number=Count("id") + ) + VIDEOS_COUNT = aggregate_videos["number"] + cache.set("VIDEOS_COUNT", VIDEOS_COUNT, timeout=CACHE_VIDEO_DEFAULT_TIMEOUT) + VIDEOS_DURATION = ( + str(timedelta(seconds=aggregate_videos["duration"])) + if aggregate_videos["duration"] + else 0 + ) + cache.set("VIDEOS_DURATION", VIDEOS_DURATION, timeout=CACHE_VIDEO_DEFAULT_TIMEOUT) return { "TYPES": types, diff --git a/pod/video/management/commands/cache_video_data.py b/pod/video/management/commands/cache_video_data.py new file mode 100644 index 0000000000..9e7a7c33dc --- /dev/null +++ b/pod/video/management/commands/cache_video_data.py @@ -0,0 +1,28 @@ +from django.core.management.base import BaseCommand +from django.core.cache import cache +from pod.video.context_processors import context_video_data +from django.core import serializers +import json + + +class Command(BaseCommand): + """Command to store video data in cache.""" + help = "Store video data in django cache : " \ + + "types, discipline, video count and videos duration" + + def handle(self, *args, **options): + """Function called to store video data in cache.""" + cache.delete_many(['DISCIPLINES', 'VIDEOS_COUNT', 'VIDEOS_DURATION', 'TYPES']) + video_data = context_video_data(request=None) + msg = 'Successfully store video data in cache' + for data in video_data: + try: + msg += "\n %s : %s" % ( + data, + json.dumps(serializers.serialize("json", video_data[data])) + ) + except (TypeError, AttributeError): + msg += "\n %s : %s" % (data, video_data[data]) + self.stdout.write( + self.style.SUCCESS(msg) + )