From 9b0fbbf5edf0fb1ee4c372ff90c8171d0077d222 Mon Sep 17 00:00:00 2001 From: Dillon Dumesnil Date: Fri, 10 Dec 2021 09:49:50 -0700 Subject: [PATCH] feat: Add in batching and a delay to backpopulate user tours This should help memory usage when running the job --- .../commands/backpopulate_user_tours.py | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/lms/djangoapps/user_tours/management/commands/backpopulate_user_tours.py b/lms/djangoapps/user_tours/management/commands/backpopulate_user_tours.py index 60ab896bf3..bc064bfc17 100644 --- a/lms/djangoapps/user_tours/management/commands/backpopulate_user_tours.py +++ b/lms/djangoapps/user_tours/management/commands/backpopulate_user_tours.py @@ -1,5 +1,7 @@ """ Management command to backpopulate User Tours. """ +import time + from django.contrib.auth import get_user_model from django.core.management.base import BaseCommand @@ -16,6 +18,10 @@ class Command(BaseCommand): """ help = 'Creates or updates a row in the UserTour table for all users in the platform.' + def add_arguments(self, parser): + parser.add_argument('--batch-delay', type=float, default=1.0, help='Time delay in each iteration') + parser.add_argument('--batch-size', type=int, default=10000, help='Batch size') + def handle(self, *args, **options): """ Backpopulates UserTour objects for all existing users who don't already have a UserTour. @@ -23,18 +29,22 @@ class Command(BaseCommand): If the user has any prior enrollments, we will treat them as an existing user, otherwise they will receive a new user treatment. """ - for user in User.objects.filter(tour__isnull=True): - if CourseEnrollment.objects.filter(user=user).exists(): - course_home_tour_status = UserTour.CourseHomeChoices.EXISTING_USER_TOUR - show_courseware_tour = False - else: - course_home_tour_status = UserTour.CourseHomeChoices.NEW_USER_TOUR - show_courseware_tour = True + batch_delay = options['batch_delay'] + batch_size = options['batch_size'] + while User.objects.filter(tour__isnull=True).exists(): + time.sleep(batch_delay) + for user in User.objects.filter(tour__isnull=True)[:batch_size]: + if CourseEnrollment.objects.filter(user=user).exists(): + course_home_tour_status = UserTour.CourseHomeChoices.EXISTING_USER_TOUR + show_courseware_tour = False + else: + course_home_tour_status = UserTour.CourseHomeChoices.NEW_USER_TOUR + show_courseware_tour = True - UserTour.objects.update_or_create( - user=user, - defaults={ - 'course_home_tour_status': course_home_tour_status, - 'show_courseware_tour': show_courseware_tour, - }, - ) + UserTour.objects.update_or_create( + user=user, + defaults={ + 'course_home_tour_status': course_home_tour_status, + 'show_courseware_tour': show_courseware_tour, + }, + )