How to restore a course run to a previous version

So you messed up a course’s content in Studio. This happens from time to time, often as the result of mistakenly importing content into the wrong course. Stay calm; if you act quickly and carefully, it should be pretty easy to fix.

This is only possible for “Split Mongo” courses, i.e. those whose course keys are in the form with course-v1:ORG+COURSE+RUN. It is not possible to restore a deprecated “Old Mongo” course, i.e. those whose course keys are in the form ORG/COURSE/RUN.

Preventing Deletion

Unfortunately, there is no way to undo destructive changes via the Studio UI. So, stop editing the course. Close Studio.

Studio saves a new “version” of a course every time you make an edit to it. This is what makes restoration possible. However, the longer you spend in the broken course, the more “versions” of the course Studio is likely to generate, thus pushing the ideal (pre-destructive-edit) version of the course further and further back in the version chain.

edXers: versions are more likely to be pruned (permanently deleted) if they are further back (~10 versions) in the version chain. Pruning generally occurs weekly on Sunday, via automated jobs (which can be paused as necessary). If it’s getting close to Sunday, then the urgency of this is higher.

edX engineers: Contact SRE and have them pause the modulestore pruning job for correct environment.

Communication

TODO: This section could use input from Partner Support.

You’ll want to alert your learner/partner support team(s) ASAP. If you’re not an engineer, you’ll want to contact one to perform the restoration (edXers: file a high-priority CR), and include a link to this guide in case the engineer has never restored a course before.

edXers: If this is outside of work hours and relates to a critical course run, it may be worth posting in #warroom and trying to get an engineer’s attention.

Restoration Steps

The restoration process has two steps: find the ID of the correct version, and then tell modulestore to point the course run at that version.

1. Find the correct version via Django Admin and MongoDB shell.

For this context you can understand courses to be stored as documents. The modulestore is “split“ it uses two different DB services. We store the “document“ version of a course in MongoDB. Using MySql, we keep a ledger which for each course run, which notes the address of active published and draft versions' documents.

So, we can look at that ledger’s history to figure out which version we want to roll back to.

For this part, you need to have the App Permission cms_course_index_operator. Once you have that permission for the relevant environment, you can then view the Studio Django Admin page for the relevant environment. Select the `split_modulestore_django` tab, and search for your course run using the search tab.

Clicking on the course run will give you the current entry in the ledger. From that page, you can click on the “history“ button in the top right to view all previous versions of this ledger.

You can choose to roll back to a date from here if you so choose, but you might also want to inspect the course structure for a particular entry. That might be a process you complete alongside a support person, who will deem a rollback “acceptable“ or not. Luckily, you are equipped with the unique ids of each document for each version of you course.

In order to find the documents themselves to inspect them, Log into the Read Replica and run /edx/bin/prod-edx-edxapp-mongo.sh (substituting prod for stage or edx for edge as necessary).

Once in that shell, run db.modulestore.structures.find({"_id" : ObjectId("<OBJECT ID>")})

where <OBJECT ID> is the object id of a document you copy/paste from django admin. it will return a long json-esque document you/partner support can look at to determine if it acceptable for your course author.

2. Reset the course run to the correct version via the management command

Making a rollback is easy once you have determined a particular version to be acceptable. Use the history button in django admin to find a version for a course, and click the “revert“ button and the bottom of the history entry to revert to that version. You can also manually enter the objectId values into the current entry if you so choose, if you wish for a bespoke combination. All that is required for that to work is for you to click “save“ at the bottom. NOTE THAT THE DRAFT AND PUBLISHED DOCUMENTS SHOULD NEVER BE THE SAME for an active entry!

Done?

Hopefully, that worked. All learner state should still safely be in the LMS, and should link back up to the restored content without any action. Huzzah!

If you hit roadblocks or found issues in this process, do comment to let us know.