fix(backend): make roms_facets/collection migrations idempotent#3930
Merged
Conversation
MariaDB/MySQL auto-commit each DDL statement, so a failure partway through 0100/0101/0103 committed the CREATE TABLE / ADD COLUMN but never advanced alembic_version. Every reboot then re-ran the migration from the top and died on "Table ... already exists", wedging the boot loop permanently. Guard the schema changes so a re-run after a partial failure recovers: - 0100: CREATE TABLE ... if_not_exists, catalog-check the index, make the backfill idempotent with an anti-join, DROP TRIGGER IF EXISTS before each CREATE TRIGGER (both MySQL and Postgres paths). - 0101: same treatment; backfill uses INSERT IGNORE / ON CONFLICT DO NOTHING, triggers dropped before recreation, view already drops first. - 0103: skip add_column for provider ids that are already present. 0102 already used if_not_exists / catalog checks; this brings the rest of the batch in line. Verified by reproducing the wedged state (version at 0099 with the later tables already present) and confirming upgrade head now recovers cleanly to 0103, plus the rom_facets and stats test suites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Greptile SummaryMakes migrations 0100, 0101, and 0103 recover safely after partially committed DDL.
Confidence Score: 5/5The PR appears safe to merge, with the changed migrations consistently handling the supported partial-application recovery paths. Existing schema objects are detected or created conditionally, backfills complete missing data without duplicate-key failures, and synchronization triggers are recreated after the schema and data steps succeed. Reviews (1): Last reviewed commit: "fix(backend): make roms_facets/collectio..." | Re-trigger Greptile |
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.
Description
Explain the changes or enhancements you are proposing with this pull request.
On the latest alpha, upgrading wedges the container in a permanent boot loop with:
Root cause: MariaDB/MySQL auto-commit each DDL statement (no transactional DDL). When migration
0100failed partway through (on the backfill or aCREATE TRIGGER), theCREATE TABLE roms_facetshad already committed, butalembic_versionnever advanced past0099. Every subsequent boot re-ran0100from the top and died onCREATE TABLE ... already exists, so the instance could never recover on its own. Migrations0100,0101, and0103were all non-idempotent and share this failure mode;0102already guarded itself withif_not_exists/ catalog checks.Changes (bringing the whole
0100-0103batch in line with0102):0100:CREATE TABLE ... if_not_exists=True; catalog-check the index (MySQL has noCREATE INDEX IF NOT EXISTS); make the backfill idempotent with aWHERE id NOT IN (...)anti-join;DROP TRIGGER IF EXISTSbefore eachCREATE TRIGGER(MySQL and Postgres paths).0101: same treatment; backfill usesINSERT IGNORE/ON CONFLICT DO NOTHING, triggers are dropped before recreation (the view already drops first).0103: skipadd_columnfor provider-id columns already present.Each is now safe to re-run after a partial failure, so a wedged instance self-heals on the next boot with no manual SQL.
Testing
alembic_versionat0099with an orphanedroms_facetstable) and confirmedalembic upgrade headnow recovers cleanly all the way to0103instead of crashing.0099with every later table/trigger/view left in place recovers to0103with no errors.0001 -> headstill works;test_rom_facets.pyandtest_stats_handler.pypass (14/14).trunk checkclean on all three files.Checklist
Please check all that apply.
Screenshots (if applicable)
AI assistance disclosure
This change was developed with AI assistance (Claude Code). The AI diagnosed the root cause, wrote the migration guards, and ran the recovery/regression tests; all changes were reviewed by the author.
🤖 Generated with Claude Code