Merge pull request #23399 from edx/mikix/update-subquery
Avoid subquery on table being updated
This commit is contained in:
@@ -242,29 +242,33 @@ class ResetScheduleTests(SharedModuleStoreTestCase):
|
||||
self.enrollment = CourseEnrollmentFactory(
|
||||
course_id=self.course.id,
|
||||
mode=CourseMode.AUDIT,
|
||||
is_active=False,
|
||||
)
|
||||
self.schedule = self.enrollment.schedule
|
||||
self.user = self.enrollment.user
|
||||
|
||||
def test_schedule_is_reset_after_enrollment_change(self):
|
||||
""" Test that an update in enrollment causes a schedule reset. """
|
||||
original_start = self.schedule.start_date
|
||||
|
||||
CourseEnrollment.enroll(self.enrollment.user, self.course.id, mode=CourseMode.VERIFIED)
|
||||
CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.VERIFIED)
|
||||
|
||||
self.schedule.refresh_from_db()
|
||||
self.assertGreater(self.schedule.start_date, original_start) # should have been reset to current time
|
||||
|
||||
def test_schedule_is_reset_to_availabilty_date(self):
|
||||
""" Test that a switch to audit enrollment resets to the availabilty date, not current time. """
|
||||
def test_schedule_is_reset_to_availability_date(self):
|
||||
""" Test that a switch to audit enrollment resets to the availability date, not current time. """
|
||||
original_start = self.schedule.start_date
|
||||
|
||||
# Switch to verified, confirm we change start date
|
||||
CourseEnrollment.enroll(self.enrollment.user, self.course.id, mode=CourseMode.VERIFIED)
|
||||
CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.VERIFIED)
|
||||
self.schedule.refresh_from_db()
|
||||
self.assertNotEqual(self.schedule.start_date, original_start)
|
||||
|
||||
CourseEnrollment.unenroll(self.user, self.course.id)
|
||||
|
||||
# Switch back to audit, confirm we change back to original availability date
|
||||
CourseEnrollment.enroll(self.enrollment.user, self.course.id, mode=CourseMode.AUDIT)
|
||||
CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.AUDIT)
|
||||
self.schedule.refresh_from_db()
|
||||
self.assertEqual(self.schedule.start_date, original_start)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from django.db.models import F, Subquery
|
||||
from django.db.models.functions import Greatest
|
||||
|
||||
from openedx.core.djangoapps.schedules.models import Schedule
|
||||
from student.models import CourseEnrollment
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@@ -54,7 +55,18 @@ def reset_self_paced_schedule(user, course_key, use_availability_date=False):
|
||||
)
|
||||
|
||||
if use_availability_date:
|
||||
schedule = schedule.annotate(start_of_access=Greatest(F('enrollment__created'), F('enrollment__course__start')))
|
||||
schedule.update(start_date=Subquery(schedule.values('start_of_access')[:1]))
|
||||
# Query enrollments to find availability date -- very similar to query above, but we can't reuse that query
|
||||
# object because mysql doesn't like a subquery of an update to reference the same table being updated.
|
||||
# Be careful attempting to remove this logic because you can't reproduce a problem locally -- in my own testing,
|
||||
# I could not reproduce in devstack, but it was happening on prod databases. So implementations vary.
|
||||
# See https://dev.mysql.com/doc/refman/8.0/en/subquery-restrictions.html
|
||||
enrollments = CourseEnrollment.objects.filter(
|
||||
user=user,
|
||||
course__id=course_key,
|
||||
course__self_paced=True,
|
||||
).annotate(
|
||||
availability=Greatest(F('created'), F('course__start')),
|
||||
)
|
||||
schedule.update(start_date=Subquery(enrollments.values('availability')[:1]))
|
||||
else:
|
||||
schedule.update(start_date=datetime.datetime.now(pytz.utc))
|
||||
|
||||
Reference in New Issue
Block a user