diff --git a/home_page_counters.json b/home_page_counters.json new file mode 100644 index 000000000..38674f419 --- /dev/null +++ b/home_page_counters.json @@ -0,0 +1,6 @@ +{ + "public_competitions": 0, + "users": 0, + "submissions": 0, + "last_updated": "2000-01-01T00:00:00.000000+00:00" +} diff --git a/src/apps/analytics/tasks.py b/src/apps/analytics/tasks.py index 8eb6f4c11..d86f153c2 100644 --- a/src/apps/analytics/tasks.py +++ b/src/apps/analytics/tasks.py @@ -1,6 +1,7 @@ import os import time import logging +import json from celery_config import app from datetime import datetime, timezone, timedelta from django.db.models import ( @@ -551,6 +552,40 @@ def create_storage_analytics_snapshot(): ) +@app.task(queue="site-worker") +def update_home_page_counters(): + starting_time = time.process_time() + logger.info("Task update_home_page_counters Started") + + # Count public competitions + public_competitions = Competition.objects.filter(published=True).count() + + # Count active users + # TODO: do not count deleted users + users = User.objects.all().count() + + # Count all submissions + submissions = Submission.objects.all().count() + + # Create counters data + counters_data = { + "public_competitions": public_competitions, + "users": users, + "submissions": submissions, + "last_updated": datetime.now(timezone.utc).isoformat() + } + + # Save latest counters in the file + log_file = "/app/home_page_counters.json" + with open(log_file, "w") as f: + json.dump(counters_data, f, indent=4) + + elapsed_time = time.process_time() - starting_time + logger.info( + "Task update_home_page_counters Completed. Duration = {:.3f} seconds".format(elapsed_time) + ) + + @app.task(queue="site-worker") # 12 hours def reset_computed_storage_analytics(): logger.info("Task reset_computed_storage_analytics started") diff --git a/src/apps/pages/views.py b/src/apps/pages/views.py index d82d4b2cd..a69ee2d10 100644 --- a/src/apps/pages/views.py +++ b/src/apps/pages/views.py @@ -14,31 +14,6 @@ class HomeView(TemplateView): def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) - # TODO: Optimize fetching the statistics - # Possibly from a file where they are written by an automated script once a day - # For now showing latest numbers from live codabench - # The following commented code is slowing down the loading of the home page - - # data = Competition.objects.aggregate( - # count=Count('*'), - # published_comps=Count('pk', filter=Q(published=True)), - # unpublished_comps=Count('pk', filter=Q(published=False)), - # ) - - # public_competitions = data['published_comps'] - # users = User.objects.all().count() - # submissions = Submission.objects.all().count() - - public_competitions = 204 - users = 12216 - submissions = 70276 - - context['general_stats'] = [ - {'label': "Public Competitions", 'count': public_competitions}, - {'label': "Users", 'count': users}, - {'label': "Submissions", 'count': submissions}, - ] - announcement = Announcement.objects.all().first() context['announcement'] = announcement.text if announcement else None diff --git a/src/settings/base.py b/src/settings/base.py index 205a7bdba..70a8fc01e 100644 --- a/src/settings/base.py +++ b/src/settings/base.py @@ -232,6 +232,10 @@ 'task': 'analytics.tasks.create_storage_analytics_snapshot', 'schedule': crontab(hour='2', minute='0', day_of_week='sun') # Every Sunday at 02:00 UTC time }, + 'update_home_page_counters': { + 'task': 'analytics.tasks.update_home_page_counters', + 'schedule': timedelta(days=1), # Run every 24 hours + }, 'reset_computed_storage_analytics': { 'task': 'analytics.tasks.reset_computed_storage_analytics', 'schedule': crontab(hour='2', minute='0', day_of_month='1', month_of_year="*/3") # Every 3 month at 02:00 UTC on the 1st diff --git a/src/templates/pages/home.html b/src/templates/pages/home.html index 3316a58b5..123bccefb 100644 --- a/src/templates/pages/home.html +++ b/src/templates/pages/home.html @@ -88,18 +88,27 @@

- {% for stat in general_stats %} -
-
-
- {{ stat.count }} -
-
- {{ stat.label }} -
-
+ +
+
+
{{ HOME_PAGE_COUNTERS_INFO.public_competitions }}
+
Public Competitions
+
+
+ +
+
+
{{ HOME_PAGE_COUNTERS_INFO.users }}
+
Users
+
+
+ +
+
+
{{ HOME_PAGE_COUNTERS_INFO.submissions }}
+
Submissions
- {% endfor %} +
diff --git a/src/utils/context_processors.py b/src/utils/context_processors.py index 1c9787aa0..edde91d0b 100644 --- a/src/utils/context_processors.py +++ b/src/utils/context_processors.py @@ -5,6 +5,8 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Set the absolute path for the version file VERSION_FILE_PATH = os.path.join(os.path.dirname(BASE_DIR), 'version.json') +# Set the absolute path for the home page counters file +HOME_PAGE_COUNTERS_FILE_PATH = os.path.join(os.path.dirname(BASE_DIR), 'home_page_counters.json') def common_settings(request): @@ -32,6 +34,18 @@ def common_settings(request): except json.JSONDecodeError: version_info = {"tag_name": "invalid"} + # Read home page counters information from the home_page_counters.json file + home_page_counters_info = {} + try: + with open(HOME_PAGE_COUNTERS_FILE_PATH) as counters_file: + home_page_counters_info = json.load(counters_file) + except Exception: + home_page_counters_info = { + "public_competitions": 0, + "users": 0, + "submissions": 0 + } + return { 'STORAGE_TYPE': settings.STORAGE_TYPE, 'MAX_EXECUTION_TIME_LIMIT': settings.MAX_EXECUTION_TIME_LIMIT, @@ -41,4 +55,5 @@ def common_settings(request): 'ENABLE_SIGN_UP': settings.ENABLE_SIGN_UP, 'ENABLE_SIGN_IN': settings.ENABLE_SIGN_IN, 'VERSION_INFO': version_info, + 'HOME_PAGE_COUNTERS_INFO': home_page_counters_info }