Remove the orphaned v5/v6/v7 search indexes#3524
Conversation
|
Claude finished @jonathangreen's task in 2m 58s —— View job Code Review
SummaryThis is a clean, well-scoped, and well-tested change. The I verified the index-naming convention matches end to end ( No actionable issues found. The merge gate in the PR description (hold until the release containing #3523 is fully on v8 in production) remains the right call. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## chore/remove-old-search-schema-revisions #3524 +/- ##
=========================================================================
Coverage 93.44% 93.44%
=========================================================================
Files 509 509
Lines 46464 46486 +22
Branches 6343 6347 +4
=========================================================================
+ Hits 43418 43441 +23
+ Misses 1969 1968 -1
Partials 1077 1077 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Reindex migrations re-point the search read/write aliases at each new index
but never delete the index they replaced, so the retired v5/v6/v7 revisions
leave orphaned circulation-works-v{5,6,7} indexes behind in the cluster. No
existing code ever removes them.
This adds a SearchService.index_remove(name) primitive and a remove_search_indices
helper that deletes the named old versions (skipping any index a read or write
alias still points at, so it can't drop the live index). A one-shot startup task
calls the helper inline for v5/v6/v7; removing a handful of indexes is a fast
metadata operation that needs no background task.
e3fd60f to
e5d49cb
Compare
Pass ignore=[404] to indices.delete so the small exists()/delete() race in index_remove resolves as a no-op instead of a spurious NotFoundError. Note in the startup task why the cleanup runs inline rather than via a Celery task, and drop the remove-me TODO: completed startup tasks are recorded and never re-run, and old task files are cleaned up periodically.
Greptile SummaryThis PR adds the final cleanup step for retiring the v5–v7 OpenSearch schema revisions: it deletes the orphaned
Confidence Score: 5/5Safe to merge once production is fully on v8; the alias-protection guard provides an in-code safeguard against accidentally dropping the live index. The alias-guard is correct and tested across three cases. The TOCTOU window in index_remove is already handled with ignore=[404]. Error propagation from pointer lookups is intentional and matches the retry-on-next-boot contract. No files require special attention; the merge gate (production fully on v8) is the only dependency. Important Files Changed
Reviews (4): Last reviewed commit: "Address review feedback on the search in..." | Re-trigger Greptile |
|
This is ready for review, but I'll keep it in draft until its ready to be merged |
Description
Stacked on top of #3523. Cleans up the orphaned
circulation-works-v5,-v6and-v7OpenSearch indexes that earlier schema revisions left behind in the cluster.When the search schema migrates to a new revision, the reindex flow creates the new index and re-points the read/write aliases at it, but it never deletes the index it replaced — so every retired revision leaves an orphaned
{base}-v{n}index sitting in the cluster, consuming shards and disk. Nothing in the codebase has ever removed them. #3523 removes the v5–v7 revision code; this PR removes the leftover indexes.This adds:
SearchService.index_remove(name)— deletes an index if it exists and reports whether it did. The service had no delete-index capability before.remove_search_indices(service, versions, *, log)helper — deletes the named old versions, with a safety guard that never deletes an index a read or write alias still points at, so it cannot drop the live index even if asked to. It's idempotent (delete-if-exists) and returns the names it removed.startup_tasks/2026_06_30_remove_old_search_indexes.py) that calls the helper inline for versions[5, 6, 7]on the next boot.Removing a handful of indexes is a fast metadata operation, so this runs inline in the startup task rather than via a background job. If OpenSearch is briefly unavailable the helper raises, the startup runner declines to record the task as done, and it simply retries on the next boot.
Important
Do not merge until the release containing #3523 has shipped and production is fully on v8. Like #3523 this is "release 2" work: the deletion is only safe once no production index is on v5/v6/v7. The helper is additionally defensive — it skips any index an alias still points at — but the merge gate is the real guarantee. Kept in draft until then.
Motivation and Context
Removing the v5–v7 revision modules (#3523) stops the code from referencing those schemas, but the actual indexes remain in the cluster forever because the migration flow only swaps aliases and never drops the old index. This reclaims that cluster state (shards, disk) as the final step of retiring those revisions.
How Has This Been Tested?
New tests, all passing under the docker tox environment:
tests/manager/search/test_service.py::TestService::test_index_remove—index_removedeletes a real index and is a no-op (returnsFalse) when it's absent.tests/manager/search/test_service.py::TestRemoveSearchIndices— three cases against the real OpenSearch fixture: the happy path (old indexes removed, the live index preserved), the alias guard (an index a read alias points at is skipped), and a no-op when the indexes don't exist.Also ran the startup-task and initialization suites to confirm the new task file is discovered and the boot wiring is unaffected.
Checklist