Repository navigation
fix: make the bulk progress feed's count fast (v0.13.10) - #403
Merged
Merged
Conversation
In 0.13.9 the first call of GET api/fx/learners/v1/learner_courses/ ran a live COUNT over the caller's whole scope: minutes for a platform-wide caller, cut at the edge after ~100 s while the database kept counting. The response shape is unchanged; `count` is now the sum of a new CourseStat.progress_count over the caller's courses (milliseconds), null with modified_since. sync_course_stats fills progress_count from the course-level completion aggregates, course keys in batches of 500 so the (course_key, aggregation_name, ...) index answers each batch as a range read: 13.3 s for the whole platform on the prod replica (an enrollment/user-checked count and an unkeyed index scan both took over 5 minutes). Learners who unenrolled after starting are therefore still counted. Migration 0013_coursestat_progress_count adds the column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Why
In 0.13.9 the first call of the bulk progress feed (
GET /api/fx/learners/v1/learner_courses/, no username) ran a live COUNT over the caller's whole scope. For a platform-wide caller that takes minutes: Cloudflare cuts the request at about 100 s while MySQL keeps counting. On 2026-10-22, six such counts were stacked on the/api/fxread replica (110–401 s each) and had to be killed.What
The response does not change:
countandpagestay in every response.countis now the sum ofCourseStat.progress_countover the caller's courses, which takes milliseconds (get_learners_progress_count).modified_since,countisnull, because a total of changed rows can't be kept in advance.sync_course_stats(the existing stats job) fills the newprogress_count. It reads the course-level completion aggregates, with course keys in batches of 500, so the(course_key, aggregation_name, …)index answers each batch as a range read.Measured on the prod read replica (read-only), 2026-10-22/24:
Trade-offs (documented and tested):
countis as fresh as the last sync.Release notes
0013_coursestat_progress_count(adds the column), so the deploy must run init (skip_init=false).0013_backfill_view_allow_write. When it rebases onto this, rename it to0014and make it depend on0013_coursestat_progress_count../manage.py lms sync_course_stats --asynconce right after the deploy. Until then everycountreads 0.CRONJOB_SCHEDULE_SYNC_COURSE_STATSfrom nightly to hourly at:20, after the hourly aggregator run.__version__0.13.10.Tests
tox -e py311-teak,py311-redwood,py311-sumac,quality: 100% coverage in each release, quality clean. New tests cover:progress_count: course-level only, above 0, counted across batches, courses with progress but no certificates;modified_since.🤖 Generated with Claude Code