CSM - Courseware Student Module Touch Points
Part of PLAT-2436, this is an attempt to discover where the StudentModule model and table are read/written, for the purpose of crafting a solution to update its primary key from a signed int to an unsigned bigint.
Direct access to the StudentModule
Selects
class_dashboardaggregates or selects across manyStudentModulerows in single queries in these places:xblock_utilsuses direct aggregate SELECT SQL executed here:https://github.com/edx/edx-platform/blob/master/openedx/core/lib/xblock_utils/__init__.py#L271
Comment: "Print out a histogram of grades on a given problem in staff member debug info."
course_blocksGets a single user/course/block row: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/course_blocks/utils.py#L25
coursewaremodel_dataGets multiple user/course/block rows: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/model_data.py#L952
Get on a single row: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/model_data.py#L1030
user_state_clientGet on multiple user/course/block rows using a chunked_filter: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/user_state_client.py#L81
Paginated iterator over all StudentModule objects for a given XBlock locator, pulling back rows in chunks: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/user_state_client.py#L414
Paginated iterator over all StudentModule objects for a given course, pulling back rows in chunks: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/user_state_client.py#L428
viewsGets all rows for a student/usage key/course (to then get their history): https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/views/views.py#L1200
gradesMgmt command
recalculate_subsection_gradespulls all rows for a learner/course/subsection modified within a certain time: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/grades/management/commands/recalculate_subsection_grades.py#L64
instructorreset_student_attemptsgets a single student/course/module state key: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor/enrollment.py#L292
instructor_analyticslist_problem_responsesgets all answers to a single problem for a course, optionally in chunks: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor_analytics/basic.py#L436
instructor_task_get_modules_to_updatefetches all rows for a course / list of usage keys / optional user, also does aget_or_create:
The admin site
Writes
instructorreset_student_attemptsoverwrites 'attempts' usingsave(): https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor/enrollment.py#L337
course_blockscoursewaremodel_dataget_or_createfor an individual row, plus a get, plus an update: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/model_data.py#L993
user_state_clientget_or_createin a loop, with potential updates usingsave(): https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/user_state_client.py#L246
instructor_task_get_modules_to_updatedoes aget_or_createin a loop: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor_task/tasks_helper/module_state.py#L427
xmodulelti_2_util'sset_user_module_scorepublishes an event that claims to updateStudentModulestate, but I'm not sure what the code path for that is: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/lti_2_util.py#L258
The admin site
Deletes
instructorreset_student_attemptscan optionally deleteStudentModulerows recursively: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor/enrollment.py#L299
The admin site
Caches
coursewareI'm unclear on how many of the caches and K/V stores in
courseware/model_data.pyaccess or storeStudentModuledata, ex:DjangoKeyValueStore&FieldDataCache: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/model_data.py#L680courseware.masquerade
MasqueradingKeyValueStoremay also store state?: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/masquerade.py#L222
Indirect access to StudentModule
LTI forces a publish of a user's score on a problem in these two places, which claims to eventually write to StudentModule:
instructor_task _get_module_instance_for_taskindirectly reads viaDjangoKeyValueStore: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor_task/tasks_helper/module_state.py#L329I suspect there are several other indirect ways that StudentModule gets accessed that are hard to grep for! Expert opinions are needed here!
Special cases
Tests that rely on
StudentModuleFactory(many)Obviously our fix must support or work around sqllite as well
BokChoy tests use a cached schema that may need to be taken into consideration:
Tests that check query counts on these tables:
StudentModuleHistoryExtendedHas event listeners an StudentModule for
post_saveandpost_deletePlus an "it's complicated" relationship with
StudentModule.