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_dashboard
 aggregates or selects across manyÂStudentModule
rows in single queries in these places:- https://github.com/edx/edx-platform/blob/master/lms/djangoapps/class_dashboard/dashboard_data.py#L37
- https://github.com/edx/edx-platform/blob/master/lms/djangoapps/class_dashboard/dashboard_data.py#L80
- https://github.com/edx/edx-platform/blob/master/lms/djangoapps/class_dashboard/dashboard_data.py#L109
- https://github.com/edx/edx-platform/blob/master/lms/djangoapps/class_dashboard/dashboard_data.py#L430
- https://github.com/edx/edx-platform/blob/master/lms/djangoapps/class_dashboard/dashboard_data.py#L494
xblock_utils
 uses 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_blocks
- Gets a single user/course/block row: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/course_blocks/utils.py#L25
courseware
model_data
- Gets 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_client
- Get 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
views
- Gets 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
grades
- Mgmt command
recalculate_subsection_grades
pulls 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
- Mgmt command
instructor
reset_student_attempts
 gets a single student/course/module state key: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor/enrollment.py#L292
instructor_analytics
list_problem_responses
gets 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_update
fetches all rows for a course / list of usage keys / optional user, also does aget_or_create
:
- The admin site
Writes
instructor
reset_student_attempts
overwrites 'attempts' usingsave()
:Â https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor/enrollment.py#L337
course_blocks
courseware
model_data
get_or_create
 for 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_client
get_or_create
 in 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_update
does aÂget_or_create
in a loop: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor_task/tasks_helper/module_state.py#L427
- Â
xmodule
lti_2_util
'sset_user_module_score
publishes an event that claims to updateÂStudentModule
state, 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
instructor
reset_student_attempts
 can optionally deleteÂStudentModule
rows recursively: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor/enrollment.py#L299
- The admin site
Caches
courseware
- I'm unclear on how many of the caches and K/V stores inÂ
courseware/model_data.py
access or storeÂStudentModule
data, ex:ÂDjangoKeyValueStore
&FieldDataCache
: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/model_data.py#L680 - courseware.masqueradeÂ
MasqueradingKeyValueStore
may also store state?: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/courseware/masquerade.py#L222
- I'm unclear on how many of the caches and K/V stores inÂ
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_task
 indirectly reads viaDjangoKeyValueStore
: https://github.com/edx/edx-platform/blob/master/lms/djangoapps/instructor_task/tasks_helper/module_state.py#L329- I 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:
StudentModuleHistoryExtended
- Has event listeners an StudentModule forÂ
post_save
andpost_delete
- Plus an "it's complicated" relationship with
StudentModule
.
- Has event listeners an StudentModule forÂ