Skip to content

Commit

Permalink
fix: clear block structure cache when usage key is not found (#33963)
Browse files Browse the repository at this point in the history
  • Loading branch information
asadali145 authored Mar 12, 2024
1 parent 794c678 commit 19c04fc
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
17 changes: 16 additions & 1 deletion lms/djangoapps/grades/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from lms.djangoapps.course_blocks.api import get_course_blocks
from lms.djangoapps.courseware.model_data import get_score
from lms.djangoapps.grades.config.models import ComputeGradesSetting
from openedx.core.djangoapps.content.block_structure.api import clear_course_from_cache
from openedx.core.djangoapps.content.block_structure.exceptions import UsageKeyNotInBlockStructure
from openedx.core.djangoapps.content.course_overviews.models import \
CourseOverview # lint-amnesty, pylint: disable=unused-import
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
Expand All @@ -44,6 +46,7 @@
DatabaseError,
ValidationError,
DatabaseNotReadyError,
UsageKeyNotInBlockStructure,
)
RECALCULATE_GRADE_DELAY_SECONDS = 2 # to prevent excessive _has_db_updated failures. See TNL-6424.
RETRY_DELAY_SECONDS = 40
Expand Down Expand Up @@ -315,14 +318,26 @@ def _update_subsection_grades(
student = User.objects.get(id=user_id)
store = modulestore()
with store.bulk_operations(course_key):
course_structure = get_course_blocks(student, store.make_course_usage_key(course_key))
course_usage_key = store.make_course_usage_key(course_key)
course_structure = get_course_blocks(student, course_usage_key)
subsections_to_update = course_structure.get_transformer_block_field(
scored_block_usage_key,
GradesTransformer,
'subsections',
set(),
)

# Clear the course cache if access is restricted and course blocks are
# cached without the restricted blocks.
if not subsections_to_update:
clear_course_from_cache(course_usage_key.course_key)
raise UsageKeyNotInBlockStructure(
"Scored block usage_key '{0}' is not found in the block_structure with root '{1}'".format(
str(scored_block_usage_key),
str(course_usage_key)
)
)

course = store.get_course(course_key, depth=0)
subsection_grade_factory = SubsectionGradeFactory(student, course, course_structure)

Expand Down
51 changes: 48 additions & 3 deletions lms/djangoapps/grades/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
from django.db.utils import IntegrityError
from django.utils import timezone
from edx_toggles.toggles.testutils import override_waffle_flag
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory, check_mongo_calls
from stevedore.extension import Extension, ExtensionManager

from common.djangoapps.student.models import CourseEnrollment, anonymous_id_for_user
from common.djangoapps.student.tests.factories import UserFactory
from common.djangoapps.track.event_transaction_utils import create_new_event_transaction_id, get_event_transaction_id
from common.djangoapps.util.date_utils import to_timestamp
from lms.djangoapps.courseware.tests.test_group_access import MemoryUserPartitionScheme
from lms.djangoapps.grades import tasks
from lms.djangoapps.grades.config.waffle import ENFORCE_FREEZE_GRADE_AFTER_COURSE_END
from lms.djangoapps.grades.constants import ScoreDatabaseTableEnum
Expand All @@ -36,6 +35,10 @@
recalculate_subsection_grade_v3
)
from openedx.core.djangoapps.content.block_structure.exceptions import BlockStructureNotFound
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import BlockFactory, CourseFactory, check_mongo_calls
from xmodule.partitions.partitions import USER_PARTITION_SCHEME_NAMESPACE, Group, UserPartition

from .utils import mock_get_score

Expand Down Expand Up @@ -209,6 +212,48 @@ def test_other_inaccessible_subsection(self, mock_subsection_signal):
{self.sequential.location, accessible_seq.location},
)

@patch('lms.djangoapps.grades.signals.signals.SUBSECTION_SCORE_CHANGED.send')
def test_problem_block_with_restricted_access(self, mock_subsection_signal):
"""
Test that `SUBSECTION_SCORE_CHANGED` is sent for a restricted problem block.
"""
self.set_up_course()

UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
[
Extension(
"memory",
USER_PARTITION_SCHEME_NAMESPACE,
MemoryUserPartitionScheme(),
None
)
],
namespace=USER_PARTITION_SCHEME_NAMESPACE
)
verified_group = Group(60, 'verified')
verified_partition = UserPartition(
0,
'Verified Partition',
'Verified Learners',
[verified_group],
scheme=UserPartition.get_scheme("memory"),
)

accessible_seq = BlockFactory.create(parent=self.chapter, category='sequential')
restricted_problem = BlockFactory.create(
parent=accessible_seq,
category='problem',
display_name='Restricted Problem',
group_access={verified_partition.id: [verified_group.id]}
)

self.recalculate_subsection_grade_kwargs['usage_id'] = str(restricted_problem.location)
verified_partition.scheme.set_group_for_user(self.user, verified_partition, verified_group)

self._apply_recalculate_subsection_grade()
assert mock_subsection_signal.call_count == 1
UserPartition.scheme_extensions = None

@ddt.data(
(ModuleStoreEnum.Type.split, 2, 41),
)
Expand Down

0 comments on commit 19c04fc

Please sign in to comment.