Skip to content

Commit e2ae2a8

Browse files
author
Tycho Hob
committed
perf: Reduce queries by passing grading policy has through when it
exists
1 parent 32ee413 commit e2ae2a8

3 files changed

Lines changed: 38 additions & 21 deletions

File tree

lms/djangoapps/grades/models.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ def bulk_read_grades(cls, user_id, course_key):
461461
)
462462

463463
@classmethod
464-
def update_or_create_grade(cls, **params):
464+
def update_or_create_grade(cls, grading_policy_hash=None, **params):
465465
"""
466466
Wrapper for objects.update_or_create.
467467
"""
@@ -490,11 +490,11 @@ def update_or_create_grade(cls, **params):
490490
grade.save()
491491

492492
cls._emit_grade_calculated_event(grade)
493-
cls._emit_openedx_persistent_subsection_grade_changed_event(grade, visible_blocks)
493+
cls._emit_openedx_persistent_subsection_grade_changed_event(grade, visible_blocks, grading_policy_hash)
494494
return grade
495495

496496
@classmethod
497-
def bulk_create_grades(cls, grade_params_iter, user_id, course_key):
497+
def bulk_create_grades(cls, grade_params_iter, user_id, course_key, grading_policy_hash=None):
498498
"""
499499
Bulk creation of grades.
500500
"""
@@ -514,7 +514,7 @@ def bulk_create_grades(cls, grade_params_iter, user_id, course_key):
514514
grades = cls.objects.bulk_create(grades)
515515
for grade, visible_blocks in zip(grades, visible_blocks_list, strict=True):
516516
cls._emit_grade_calculated_event(grade)
517-
cls._emit_openedx_persistent_subsection_grade_changed_event(grade, visible_blocks)
517+
cls._emit_openedx_persistent_subsection_grade_changed_event(grade, visible_blocks, grading_policy_hash)
518518
return grades
519519

520520
@classmethod
@@ -545,21 +545,26 @@ def _emit_grade_calculated_event(grade):
545545
events.subsection_grade_calculated(grade)
546546

547547
@staticmethod
548-
def _emit_openedx_persistent_subsection_grade_changed_event(grade, visible_blocks):
548+
def _emit_openedx_persistent_subsection_grade_changed_event(grade, visible_blocks, grading_policy_hash=None):
549549
"""
550550
When called emits an event when a persistent subsection grade is created or updated.
551+
552+
``grading_policy_hash`` should be supplied by callers that already have the course's
553+
block structure loaded, so it can be reused instead of loading the course from the
554+
modulestore (an extra query per event). When not provided, it is computed here.
551555
"""
552556
# .. event_implemented_name: PERSISTENT_SUBSECTION_GRADE_CHANGED
553557
# .. event_type: org.openedx.learning.course.persistent_subsection_grade.changed.v1
554-
try:
555-
grading_policy_hash = GradesCourseData(user=None, course_key=grade.course_id).grading_policy_hash
556-
except Exception: # pylint: disable=broad-except
557-
grading_policy_hash = ""
558-
log.debug(
559-
"Unable to compute grading_policy_hash for course %s",
560-
grade.course_id,
561-
exc_info=True,
562-
)
558+
if grading_policy_hash is None:
559+
try:
560+
grading_policy_hash = GradesCourseData(user=None, course_key=grade.course_id).grading_policy_hash
561+
except Exception: # pylint: disable=broad-except
562+
grading_policy_hash = ""
563+
log.debug(
564+
"Unable to compute grading_policy_hash for course %s",
565+
grade.course_id,
566+
exc_info=True,
567+
)
563568

564569
xblocks_scoring_data = [
565570
XBlockWithScoringData(

lms/djangoapps/grades/subsection_grade.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,17 @@ def __init__(self, subsection, course_structure, submissions_scores, csm_scores)
281281

282282
super().__init__(subsection, all_total, graded_total)
283283

284-
def update_or_create_model(self, student, score_deleted=False, force_update_subsections=False):
284+
def update_or_create_model(
285+
self, student, score_deleted=False, force_update_subsections=False, grading_policy_hash=None
286+
):
285287
"""
286288
Saves or updates the subsection grade in a persisted model.
287289
"""
288290
if self._should_persist_per_attempted(score_deleted, force_update_subsections):
289-
model = PersistentSubsectionGrade.update_or_create_grade(**self._persisted_model_params(student))
291+
model = PersistentSubsectionGrade.update_or_create_grade(
292+
grading_policy_hash=grading_policy_hash,
293+
**self._persisted_model_params(student),
294+
)
290295

291296
if hasattr(model, 'override'):
292297
# When we're doing an update operation, the PersistentSubsectionGrade model
@@ -299,7 +304,7 @@ def update_or_create_model(self, student, score_deleted=False, force_update_subs
299304
return model
300305

301306
@classmethod
302-
def bulk_create_models(cls, student, subsection_grades, course_key):
307+
def bulk_create_models(cls, student, subsection_grades, course_key, grading_policy_hash=None):
303308
"""
304309
Saves the subsection grade in a persisted model.
305310
"""
@@ -309,7 +314,9 @@ def bulk_create_models(cls, student, subsection_grades, course_key):
309314
if subsection_grade
310315
if subsection_grade._should_persist_per_attempted() # pylint: disable=protected-access
311316
]
312-
return PersistentSubsectionGrade.bulk_create_grades(params, student.id, course_key)
317+
return PersistentSubsectionGrade.bulk_create_grades(
318+
params, student.id, course_key, grading_policy_hash=grading_policy_hash
319+
)
313320

314321
def _should_persist_per_attempted(self, score_deleted=False, force_update_subsections=False):
315322
"""

lms/djangoapps/grades/subsection_grade_factory.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ def create(self, subsection, read_only=False, force_calculate=False):
5757
if read_only:
5858
self._unsaved_subsection_grades[subsection_grade.location] = subsection_grade
5959
else:
60-
grade_model = subsection_grade.update_or_create_model(self.student)
60+
grade_model = subsection_grade.update_or_create_model(
61+
self.student,
62+
grading_policy_hash=self.course_data.grading_policy_hash,
63+
)
6164
self._update_saved_subsection_grade(subsection.location, grade_model)
6265
return subsection_grade
6366

@@ -66,7 +69,8 @@ def bulk_create_unsaved(self):
6669
Bulk creates all the unsaved subsection_grades to this point.
6770
"""
6871
CreateSubsectionGrade.bulk_create_models(
69-
self.student, list(self._unsaved_subsection_grades.values()), self.course_data.course_key
72+
self.student, list(self._unsaved_subsection_grades.values()), self.course_data.course_key,
73+
grading_policy_hash=self.course_data.grading_policy_hash,
7074
)
7175
self._unsaved_subsection_grades.clear()
7276

@@ -100,7 +104,8 @@ def update(self, subsection, only_if_higher=None, score_deleted=False, force_upd
100104
grade_model = calculated_grade.update_or_create_model(
101105
self.student,
102106
score_deleted,
103-
force_update_subsections
107+
force_update_subsections,
108+
grading_policy_hash=self.course_data.grading_policy_hash,
104109
)
105110
self._update_saved_subsection_grade(subsection.location, grade_model)
106111

0 commit comments

Comments
 (0)