Repository navigation
Conversation
This was referenced Oct 14, 2026
Contributor Report for @jeffspahr
|
Signed-off-by: Jeff Spahr <spahrj@gmail.com> (cherry picked from commit f31b962)
Signed-off-by: Jeff Spahr <spahrj@gmail.com> (cherry picked from commit a679be9)
Signed-off-by: Jeff Spahr <spahrj@gmail.com> (cherry picked from commit ad45240)
Signed-off-by: Jeff Spahr <spahrj@gmail.com> (cherry picked from commit d21b175)
jeffspahr
force-pushed
the
codex/218-automatic-retention-indexes
branch
from
October 14, 2026 22:23
bafaed2 to
69b1430
Compare
Collaborator
|
AA review summary for #14877: fix(backend): automate retention index preparation on 2.18
|
Collaborator
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: droctothorpe The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
New changes are detected. LGTM label has been removed. |
55 of 58 tasks
30 tasks
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.
Problem
Enabling run retention currently requires operators to create two database indexes manually. On large run histories, that makes index scheduling and recovery an operator task, while simply moving the SQL into API startup would risk blocking readiness and triggering retention catch-up as soon as a lengthy build finishes.
Changes
The elected GC worker now prepares the required indexes sequentially in the background. API startup does not await this DDL. Existing compatible, optimizer-visible indexes are reused; MySQL requires
ALGORITHM=INPLACE, LOCK=NONE, and PostgreSQL usesCREATE INDEX CONCURRENTLY. No column narrowing, copying fallback or destructive index replacement is allowed.RUNS_GC_INDEX_BUILD_TIMEOUT: positive duration per index attempt, default 12h, separate from the five-second metadata-lock wait.RUNS_GC_INDEX_PREPARE_ONLY=true: prepare indexes without archiving/deleting, even with retention windows disabled. Apply consistently across replicas/installations; it cannot pause an old leader before that leader receives the configuration.RUNS_GC_INTERVALbefore collecting. GC remains gated on both valid indexes. This separates preparation from catch-up; prepare-only provides an explicit activation step for large installations.Retention remains disabled by default. Already-configured retention that was paused by missing indexes can now begin archival/deletion automatically after preparation and the interval. The release notes explain prepare-only staging and the remaining operational limits. These settings apply to retention indexes, independently of the JobUUID lookup-index work in #14874.
Verification
common,gc,client_managerand API-server package tests passed, including configuration validation, preparation-only safety, first-leader/build/recovery separation, retries and cancellation.Operational limits
Online creation consumes I/O, CPU and disk and still takes brief metadata locks. The configurable deadline bounds the client attempt; MySQL server cleanup may outlast cancellation, retaining the session advisory lock so another preparer cannot overlap it. PostgreSQL cancellation can leave an invalid index. The preparer now automatically recovers abandoned indexes matching the reserved name and exact expected definition using concurrent drop/rebuild within the same per-index deadline. Active or waiting database maintenance defers recovery. Conflicting definitions, custom storage settings and nondefault tablespaces remain untouched. Manual DDL on these managed names must be coordinated by stopping preparers or taking their advisory lock; activity checks cannot serialize arbitrary administrator DDL. Failures pause retention, not API startup.
Prepare-only can be enabled with retention disabled to build ahead of activation. Catch-up is a separate batched workload and can still be substantial. Existing valid indexes remain on disable/rollback. This is the release-2.18 backport of #14876; merge the master PR first. Tracking: #14421.
Backport validation: all four affected Go packages passed on this branch, as did MySQL/PostgreSQL recovery, ownership, visibility and metadata-lock tests, required hooks and the warning-as-error docs build. The populated performance evidence above comes from the identical preparation/GC implementation on the master candidate; it is not a separate 100 GB acceptance run. Adaptation is limited to release-note placement and the release-specific documentation link.
Interrupted PostgreSQL build recovery
Real PostgreSQL 16 tests interrupt a concurrent build, verify that it leaves an invalid index, and recover without manual SQL. Ten application read/write cycles complete while the replacement concurrent build is active. Tests also preserve an active external build and invalid indexes with wrong columns, descending order, expressions, nondefault operator classes/collations and custom storage settings. Retention remains paused until both indexes are ready, then waits the separate collection interval.
MySQL interruption and database-crash validation
Added an opt-in Docker harness,
python3 test/retention-index-mysql-recovery.py, that creates and destroys only its own database. On 262,144 rows with 1 KiB payloads, it interrupts measured InnoDB scan/sort work after 25% of the current stage estimate, first by client cancellation and then by SIGKILL/restart with the same database volume. The production preparer retries without index-cleanup SQL. Tests require successful read/write cycles during recovery builds, usable indexes, the acknowledged pre-crash write, all rows, and unchanged InnoDB table identity. The crash case requires writes during reconstruction of the interrupted lifecycle index itself. Database downtime interrupts writes; the continuity claim applies to online builds before/after restart.MySQL 8.0.46 validation passed. Crash recovery reconnected in 11.49 seconds, with 590 lifecycle and 593 archived read/write cycles completing during the subsequent builds; the largest observed cycle was 213 ms. These fixture measurements are not a 100 GB latency or recovery-time guarantee.
The identical fixture also passed on MySQL 8.4.11 against the 2.18 backport: crash reconnect 4.65 seconds, 236 lifecycle and 247 archived read/write cycles completed during rebuilds, maximum observed cycle 229 ms. Ordinary package tests, repository hooks and documentation build passed.
Release-base reconciliation
Rebased onto release-2.18
90dcc99a9. Resolved the release-note overlap by retaining both the Python support update and the retention rollout guidance. The retention implementation and regression tests are unchanged. Release-note hooks, whitespace checks, and freshgo test ./backend/src/common ./backend/src/apiserver/gc ./backend/src/apiserver/client_manager ./backend/src/apiserver -count=1passed.