Repository navigation
feat: plan runs in resumable pages of ids - #32
Merged
Merged
Conversation
The dripper walked the whole scope with in_batches and plucked every batch again (two queries per batch), created all batches in a single transaction, and returned early on any run that was not enqueued. A 16M-row scope took hours to plan, and a worker killed mid-planning left the run in running with no batches forever. Planning now pages through the scope's primary keys 10k ids per query and commits each page, so children start while the rest is planned. The cursor is the last planned batch, read under a row lock on the run, so a retried dripper resumes without duplicating batches. total_count is written once planning ends; until then finalize_if_batches_finished! leaves the run running.
json 3.0 dropped the quirks_mode option that ActiveSupport 7.2/8.0 still passes when encoding JSON, so loading the test schema (json column default) aborted before any example ran. These builds have been red on main since json 3.0 shipped.
ccebrecos
marked this pull request as ready for review
October 13, 2026 13:27
rogercampos
approved these changes
Oct 13, 2026
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
Planning a large run took hours, and a worker restart in the middle of it left the run stuck forever.
Dripperwalked the scope within_batchesand plucked each batch again, two queries per batch. It created every batch in one transaction, so no child could start until the last batch existed. ForProjectManagement::BackfillCostRecordsLegacyin the monorepo (~16M rows,batch_size: 100) that is ~320k queries, and planning takes hours.runningbefore planning, and the dripper returned early on anything that was notenqueued. When a deploy killed the worker mid-plan, the retried job did nothing. The run sat inrunningwith 0 batches forever (prod runs 9459–9652, 10205 and 10210).What
WHERE id > last planned id ORDER BY id LIMIT 10000) and cuts each page into batches ofbatch_size. Batches,total_countandprocessed_countstay exact, and sparse scopes never get empty batches. Plain min/max id ranges were ruled out: a company-scoped run would have become ~160k mostly empty batches.max_parallel_batchesis respected as before.finish_id, read under a row lock on the run. A retried dripper resumes after it and never plans the same ids twice. No schema change.BackfillRun#planning?: a run is still planning while it isrunningwithout atotal_count, which is written when planning ends.finalize_if_batches_finished!leaves a planning run alone, and the dripper finalizes it at the end.amount_of_elements: caps the planned records at the first N matching ids, across pages.Tests
bundle exec rspec: 321 examples, 0 failures.rubocop: clean.New examples cover:
amount_of_elementsacross pagesplanning?Removing the planning guard fails 3 of them.
CI
The Rails 7.2 and 8.0 builds have been red on
mainsince json 3.0 shipped: it dropped thequirks_modeoption ActiveSupport 7.2/8.0 still passes, so loading the test schema aborted before any example ran. A separate commit pinsjson < 3in those two gemfiles.Follow-up
Bump
data_dripin the monorepo, then re-runBackfillCostRecordsLegacy. Stuck runs 10205/10210 count as planning after the bump, soDataDrip::Dripper.perform_later(run)resumes them (or stop them).Jira: FCT-65262