diff --git a/osuchan/settings.py b/osuchan/settings.py index 074bfe1..453650f 100644 --- a/osuchan/settings.py +++ b/osuchan/settings.py @@ -3,6 +3,7 @@ """ import os +from datetime import timedelta from celery.schedules import crontab from pydantic_settings import BaseSettings @@ -203,6 +204,10 @@ class EnvSettings(BaseSettings): "update-top-global-members-every-day": { "task": "profiles.tasks.dispatch_update_all_global_leaderboard_top_members", "schedule": crontab(minute="0", hour="0"), # midnight UTC + "kwargs": { + "limit": 100, + "cooldown_seconds": timedelta(hours=12).total_seconds(), + }, }, "update-global-leaderboard-top-5-score-cache-every-hour": { "task": "leaderboards.tasks.dispatch_update_global_leaderboard_top_5_score_cache", diff --git a/profiles/services.py b/profiles/services.py index 6f7c7d9..6a6a8e1 100644 --- a/profiles/services.py +++ b/profiles/services.py @@ -53,7 +53,10 @@ def fetch_user(user_id=None, username=None, gamemode=Gamemode.STANDARD): @transaction.atomic def refresh_user_from_api( - user_id=None, username=None, gamemode: Gamemode = Gamemode.STANDARD + user_id=None, + username=None, + gamemode: Gamemode = Gamemode.STANDARD, + cooldown_seconds: int = 300, ): """ Fetch and add user with top 100 scores @@ -65,7 +68,8 @@ def refresh_user_from_api( user_stats = fetch_user(user_id=user_id, username=username, gamemode=gamemode) if user_stats is not None and user_stats.last_updated > ( - datetime.utcnow().replace(tzinfo=timezone.utc) - timedelta(minutes=5) + datetime.utcnow().replace(tzinfo=timezone.utc) + - timedelta(seconds=cooldown_seconds) ): # User was last updated less than 5 minutes ago, so just return it return user_stats diff --git a/profiles/tasks.py b/profiles/tasks.py index f0960d7..1193ae4 100644 --- a/profiles/tasks.py +++ b/profiles/tasks.py @@ -13,7 +13,9 @@ @shared_task -def dispatch_update_all_global_leaderboard_top_members(limit: int = 100): +def dispatch_update_all_global_leaderboard_top_members( + limit: int = 100, cooldown_seconds: int = 500 +): """ Dispatches update_user tasks for the top members of all global leaderboards """ @@ -21,7 +23,7 @@ def dispatch_update_all_global_leaderboard_top_members(limit: int = 100): members = leaderboard.memberships.order_by("-pp")[:limit].values("user_id") for member in members: - update_user.delay(member["user_id"], leaderboard.gamemode) + update_user.delay(member["user_id"], leaderboard.gamemode, cooldown_seconds) @shared_task @@ -39,11 +41,15 @@ def dispatch_update_community_leaderboard_members( @shared_task -def update_user(user_id: int, gamemode: int = Gamemode.STANDARD): +def update_user( + user_id: int, gamemode: int = Gamemode.STANDARD, cooldown_seconds: int = 500 +): """ Runs an update for a given user """ - user_stats = refresh_user_from_api(user_id=user_id, gamemode=Gamemode(gamemode)) + user_stats = refresh_user_from_api( + user_id=user_id, gamemode=Gamemode(gamemode), cooldown_seconds=cooldown_seconds + ) if user_stats is not None: update_memberships.delay( user_id=user_stats.user_id, gamemode=user_stats.gamemode