mirror of
https://github.com/barkeser2002/offline-db.git
synced 2026-09-25 02:19:59 +03:00
Current Focus Mode: A (The Medic) Changes Made: - Refactored `users/services.py` to optimize badge checking logic. - Implemented bulk fetching of `Badge` objects and `UserBadge` slugs to avoid N+1 queries. - Updated `check_badges` and `check_chat_badges` to check against in-memory sets before awarding. - Added `users/tests/test_services_performance.py` to verify query count reduction (baseline 56 -> <30). - Fixed concurrency handling by using `bulk_create(ignore_conflicts=True)`. Impact on System: - Significantly reduced database load during user actions (watching, chatting, etc.) that trigger badge checks. - Improved scalability of the badge system. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
53 lines
2.2 KiB
Python
53 lines
2.2 KiB
Python
from django.test import TestCase
|
|
from django.contrib.auth import get_user_model
|
|
from django.test.utils import CaptureQueriesContext
|
|
from django.db import connection
|
|
from users.services import check_badges
|
|
from users.models import Badge, UserBadge
|
|
from content.models import Anime, Subscription, Review
|
|
|
|
User = get_user_model()
|
|
|
|
class BadgePerformanceTests(TestCase):
|
|
def setUp(self):
|
|
self.user = User.objects.create_user(username='perftest', password='password')
|
|
# Badges should be seeded by migrations
|
|
# Verify a few key badges exist
|
|
self.assertTrue(Badge.objects.filter(slug='critic').exists())
|
|
self.assertTrue(Badge.objects.filter(slug='collector').exists())
|
|
|
|
def test_check_badges_query_count(self):
|
|
# Create some conditions to trigger badges
|
|
anime = Anime.objects.create(title='Test Anime')
|
|
Subscription.objects.create(user=self.user, anime=anime)
|
|
Review.objects.create(user=self.user, anime=anime, rating=10, text='Great!')
|
|
|
|
# Run check_badges once to warm up (and award badges if logic works)
|
|
check_badges(self.user)
|
|
|
|
# Now run again. It should check existing badges and NOT award duplicates.
|
|
# This is where we want to minimize queries (checking "if not exists").
|
|
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
check_badges(self.user)
|
|
|
|
# Without optimization, this will do:
|
|
# 1 query for each badge to get the Badge object (unless cached, but local get() isn't cached across calls usually)
|
|
# 1 query for each badge to check UserBadge exists
|
|
# There are ~18 badges. So ~36 queries.
|
|
|
|
print(f"\nQueries executed: {len(ctx.captured_queries)}")
|
|
|
|
# Optimized version should be well under 30 queries (was 56)
|
|
self.assertLess(len(ctx.captured_queries), 30)
|
|
|
|
def test_badges_awarded_correctly(self):
|
|
# Create a review to trigger the badge
|
|
anime = Anime.objects.create(title='Test Anime 2')
|
|
Review.objects.create(user=self.user, anime=anime, rating=10, text='Great!')
|
|
|
|
# Verify 'critic' badge is awarded
|
|
check_badges(self.user)
|
|
critic = Badge.objects.get(slug='critic')
|
|
self.assertTrue(UserBadge.objects.filter(user=self.user, badge=critic).exists())
|