Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Internal issue: https://2u-internal.atlassian.net/browse/ENT-9961
Other PRs that are part of this:
Description
Add a Foreign Key, using Django’s from the EnterpriseCustomerUser model to the auth.User model. This will help greatly simplify the means by which we support filtering/searching/sorting on user fields (e.g. first/last name, email, etc.) in the context of Enterprise DRF viewsets.
This will require multiple PRs to avoid performance problems. This specific PR adds the new field without index and without foreign key reference.
Strategy
Zero-Downtime Step-by-Step Approach (Foreign Key Last)
Step 1: Add Nullable Column Without Constraint (Non-Blocking)
This operation is instant in Aurora when the column is nullable.
Non-blocking because the column is nullable and no default is set.
Step 2: Create Index on the New Column (Online, Non-Blocking)
Index creation in Aurora MySQL is online with these options:
Why this is critical:
MySQL uses the index for fast FK validation later, making the FK addition much faster and non-blocking.
Step 3: Backfill Data in Small Batches (Without FK Checks)
Because there’s no foreign key constraint yet, backfilling is fast and won’t lock the table.
Use small batches (size 1000) to avoid saturating the I/O or CPU.
The backfill should copy over the value from
user_id
to the new field.This should use a management command. The management command can easily run in batches and be monitored, and it reduces the risk of downtime versus using a data migration.
At the same time, add something to the EnterpriseCustomerUser.save() method (or maybe a signal handler?) that will update user_fk with the value in user_id on save. That will help ensure that we don't end up with new ECU records created that don't copy over the data.
Step 4: Validate Data Integrity Before Adding FK
user_id
anduser_fk
are identical and not nullStep 5: Add the Foreign Key Constraint (Online, Minimal Locking)
Finally, add the foreign key constraint using Aurora’s online DDL. For this, 'foreign_key_checks' must be temporarily disabled in the session to support the inplace algorithm:
Why this avoids downtime:
ALGORITHM=INPLACE: Adds the constraint without copying the entire table.
LOCK=NONE: Ensures DML operations (INSERT/UPDATE/DELETE) can continue during the operation.
Step 6: validate data integrity again after adding FK
Merging this
This should be a series of PRs that are merged and deployed in order.
Merge checklist:
requirements/*.txt
files)base.in
if needed in production but edx-platform doesn't install ittest-master.in
if edx-platform pins it, with a matching versionmake upgrade && make requirements
have been run to regenerate requirementsmake static
has been run to update webpack bundling if any static content was updated./manage.py makemigrations
has been run./manage.py lms makemigrations
in the shell.Post merge:
(so basically once your build finishes, after maybe a minute you should see the new version in PyPi automatically (on refresh))
make upgrade
in edx-platform will look for the latest version in PyPi.