Add versioned auto-migration for table configs and schemas - #19270
Open
xiangfu0 wants to merge 2 commits into
Open
Add versioned auto-migration for table configs and schemas#19270xiangfu0 wants to merge 2 commits into
xiangfu0 wants to merge 2 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #19270 +/- ##
============================================
- Coverage 67.12% 67.10% -0.03%
Complexity 1424 1424
============================================
Files 3462 3468 +6
Lines 220677 220832 +155
Branches 35255 35275 +20
============================================
+ Hits 148136 148195 +59
- Misses 60708 60809 +101
+ Partials 11833 11828 -5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
Author
Self-review pass (multi-domain) + fixes appliedRan an independent multi-domain review over the branch diff. 0 CRITICAL, 7 MAJOR. Addressed the substantive findings in the latest commit: Fixed
Deferred (tracked, low-risk)
All precommit checks (spotless, license, checkstyle: 0 violations) pass on the four touched modules; unit suites green (spi 29, segment-local 6, controller 6). |
xiangfu0
force-pushed
the
cs_GqTMcOVI6Y/feature/config-schema-auto-migration
branch
from
August 16, 2026 09:04
e92acee to
2cdc824
Compare
intentlab-ai
Bot
force-pushed
the
cs_GqTMcOVI6Y/feature/config-schema-auto-migration
branch
from
August 17, 2026 06:29
2cdc824 to
04da9d3
Compare
xiangfu0
force-pushed
the
cs_GqTMcOVI6Y/feature/config-schema-auto-migration
branch
from
August 18, 2026 09:04
04da9d3 to
15417f5
Compare
Introduce a versioned config-migration framework that transparently upgrades stored TableConfigs and Schemas to the current version, so that cluster upgrades do not surprise users with configs the new controller can no longer parse or validate. - pinot-spi: new org.apache.pinot.spi.config.migration package with an ordered migrator chain (ConfigMigrator/TableConfigMigrator/SchemaMigrator, ConfigMigrationRegistry, MigrationResult, ConfigMigrationUtils). Version markers are rollback-safe: Schema gains a configMigrationVersion field (ignored by older readers), TableConfig uses a controller-managed config.migration.version custom-config key. - pinot-segment-local: first concrete migrator (v0 -> v1) folds deprecated ingestion fields (tableIndexConfig.streamConfigs, segmentsConfig.segmentPushType/segmentPushFrequency) into ingestionConfig, finally wiring TableConfigUtils.convertFromLegacyTableConfig into a live path. - pinot-controller: ConfigMigrationManager periodic task (leader-only, retry on next cycle) reads each stored config as-is, runs the chain, and persists through the standard PinotHelixResourceManager write path so broker/server caches are refreshed. Version-checked writes never clobber concurrent edits; a missing schema is treated as transient, not a failure. Enabled by default via controller.config.migration.* with success/failure metrics. - pinot-common: fix toTableConfig to preserve env-var substitution when applyDecorator is false; add raw-read getTableConfigWithVersion overload. Tests cover deprecated stream-only, batch-only, and combined configs upgrading to the new ingestionConfig shape, ZK serialization round-trips, version-marker round-trips, backward/forward-compatible JSON, and the controller task's persist/skip/validation/metric paths.
- Fix a latent infinite-loop: schema marker-only migrations were persisted via PinotHelixResourceManager.updateSchema, which short-circuits on schema.equals(oldSchema) — and Schema.equals() excludes the migration marker, so the marker never persisted and the schema re-migrated every cycle. Persist the schema directly via ZKMetadataProvider.setSchema and send refresh messages best-effort so caches converge. - Default the feature OFF (opt-in for the first release): it rewrites stored ZK configs cluster-wide, so operators enable it after upgrading all nodes. - Short-circuit ZK reads when a migration chain is empty (no wasted schema reads with the shipped empty schema chain); fetch the schema once per table. - Document the rolling-upgrade/rollback implication of clearing deprecated fields on the migrator; document the controller-managed reserved custom-config key; rename MIGRATION_VERSION_KEY -> CONFIG_MIGRATION_VERSION_KEY. - Tests: deprecated ingestion-config collision folding (existing ingestionConfig wins), schema marker is actually persisted + refresh sent + migrated once across hybrid halves, empty-chain short-circuit, and Schema serialization via the full objectToString path.
xiangfu0
force-pushed
the
cs_GqTMcOVI6Y/feature/config-schema-auto-migration
branch
from
August 20, 2026 09:11
15417f5 to
9eb0a5e
Compare
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.
Summary
Adds a versioned config-migration framework that transparently upgrades stored
TableConfigs andSchemas to the current version on the controller, so cluster upgrades don't surprise users with configs the new controller can no longer parse or validate.The migration runs as a leader-only controller periodic task. For every table it reads the config exactly as stored, runs an ordered migrator chain, and — only if something changed — persists the result through the standard
PinotHelixResourceManagerwrite path (version-checked write plus broker/server cache-refresh messages). It's idempotent: once everything is current, runs are cheap no-ops.What's included
pinot-spi— neworg.apache.pinot.spi.config.migrationpackage:ConfigMigrator/TableConfigMigrator/SchemaMigrator,ConfigMigrationRegistry(dense ordered chain),MigrationResult,ConfigMigrationUtils. Version markers are rollback-safe:Schemagains aconfigMigrationVersionfield (older readers ignore it via@JsonIgnoreProperties),TableConfiguses a controller-managedconfig.migration.versioncustom-config key.pinot-segment-local— first concrete migrator (v0 → v1) folds deprecated ingestion fields (tableIndexConfig.streamConfigs,segmentsConfig.segmentPushType/segmentPushFrequency) intoingestionConfig, finally wiring the previously test-onlyTableConfigUtils.convertFromLegacyTableConfiginto a live path. Schema chain ships empty (framework ready; no placeholder transforms).pinot-controller—ConfigMigrationManagerperiodic task + wiring inBaseControllerStarter; config keys inControllerConf;CONFIG_MIGRATION_SUCCESS/CONFIG_MIGRATION_FAILUREmeters.pinot-common— fixestoTableConfigto preserve env-var substitution whenapplyDecorator=false; adds a raw-readgetTableConfigWithVersionoverload.Configuration
controller.config.migration.enabledtruefalseto opt outcontroller.config.migration.frequencyPeriod1hcontroller.config.migration.initialDelaySecondscontroller.config.migration.cronExpressionSafety / compatibility
Tests
pinot-segment-local): stream-only, batch-only, and combined deprecated configs fold intoingestionConfig; deprecated fields cleared; marker stamped; survives a ZK ZNRecord serialization round-trip; already-migrated config is a no-op.pinot-spi): in-order chain, version-compare skip, downgrade left untouched, dense-ordering enforced, TableConfig marker JSON round-trip (preserving user custom configs), Schema marker round-trip + unknown-property tolerance.All precommit checks pass (spotless, license, checkstyle: 0 violations) across the four touched modules.
Notes for reviewers
controller.config.migration.*keys.Schemafield — flagging for plugin-maintaining teams (additive, rollback-safe).