Skip to content

feat(inkless): Set migrating partitions in KRaft metadata#580

Merged
jeqo merged 4 commits intomainfrom
giuseppelillo/fix-fetch-routing-diskless
Apr 24, 2026
Merged

feat(inkless): Set migrating partitions in KRaft metadata#580
jeqo merged 4 commits intomainfrom
giuseppelillo/fix-fetch-routing-diskless

Conversation

@giuseppelillo
Copy link
Copy Markdown
Contributor

@giuseppelillo giuseppelillo commented Apr 23, 2026

When service fetch requests, it's necessary to discern between a topic being migrated from classic to diskless but that has not yet committed the disklessStartOffset to KRaft (in this case fetch still need to go through UnifiedLog) and a full diskless topic (fetch goes through diskless read path).
Introduce a new sentinel value (-2) for PartitionRegistration.classicToDisklessStartOffset that indicates that the partition is being migrated from classic to diskless.

Before these changes:

  1. Classic topic: diskless.enable=false, PartitionRegistration.classicToDisklessStartOffset = -1
  2. Full diskless topic: diskless.enable=true, PartitionRegistration.classicToDisklessStartOffset = -1
  3. Classic topic being migrated to diskless, that has not committed the diskless start offset yet to KRaft: diskless.enable=true, PartitionRegistration.classicToDisklessStartOffset = -1
  4. Classic topic being migrated to diskless, that has committed the diskless start offset to KRaft: diskless.enable=true, PartitionRegistration.classicToDisklessStartOffset = $disklessStartOffset

Case 2 and 3 are equal, even though 2 requires reading from UnifiedLog and 3 needs to read from diskless path.

After the change:

  1. Classic topic: diskless.enable=false, PartitionRegistration.classicToDisklessStartOffset = -1
  2. Full diskless topic: diskless.enable=true, PartitionRegistration.classicToDisklessStartOffset = -1
  3. Classic topic being migrated to diskless, that has not committed the diskless start offset yet to KRaft: diskless.enable=true, PartitionRegistration.classicToDisklessStartOffset = -2
  4. Classic topic being migrated to diskless, that has committed the diskless start offset to KRaft: diskless.enable=true, PartitionRegistration.classicToDisklessStartOffset = $disklessStartOffset

All cases can be individually distinguished.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a “migration pending” state for classic→diskless partition migration and wires it through controller metadata updates and broker fetch behavior so partitions can be marked pending in KRaft metadata before the actual diskless start offset is committed.

Changes:

  • Introduce CLASSIC_TO_DISKLESS_MIGRATION_PENDING = -2 as a new sentinel for classicToDisklessStartOffset.
  • Accept classicToDisklessStartOffset = -2 in InitDisklessLog and add controller logic to mark partitions pending when enabling diskless via incremental alter configs.
  • Update ReplicaManager fetch routing and add unit tests covering pending-state round trips, merges, and fetch/init behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
metadata/src/main/java/org/apache/kafka/metadata/PartitionRegistration.java Adds a new sentinel constant for “migration pending”.
metadata/src/main/java/org/apache/kafka/controller/ReplicationControlManager.java Treats non-negative offsets as “already initialized” and introduces a helper to mark partitions migration-pending.
metadata/src/main/java/org/apache/kafka/controller/QuorumController.java Appends migration-pending partition records during incrementalAlterConfigs when diskless is enabled.
core/src/main/scala/kafka/server/ReplicaManager.scala Routes fetches to UnifiedLog when migration is pending and adjusts control-plane init trigger to handle any negative→nonnegative transition.
metadata/src/test/java/org/apache/kafka/metadata/PartitionRegistrationTest.java Adds tests for pending-state record round-trip and merge semantics.
metadata/src/test/java/org/apache/kafka/controller/ReplicationControlManagerTest.java Adds tests ensuring InitDisklessLog accepts pending partitions and rejects already-initialized partitions.
core/src/test/scala/unit/kafka/server/ReplicaManagerTest.scala Adds fetch behavior tests for migration-pending partitions under managed/unmanaged replicas.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread metadata/src/main/java/org/apache/kafka/controller/QuorumController.java Outdated
Comment thread metadata/src/main/java/org/apache/kafka/controller/ReplicationControlManager.java Outdated
Comment thread metadata/src/main/java/org/apache/kafka/controller/QuorumController.java Outdated
@giuseppelillo giuseppelillo marked this pull request as ready for review April 24, 2026 09:45
List<ApiMessageAndVersion> allRecords = BoundedList.newArrayBacked(MAX_RECORDS_PER_USER_OP);
allRecords.addAll(result.records());
allRecords.addAll(migrationRecords);
return ControllerResult.of(allRecords, result.response());
Copy link
Copy Markdown
Contributor

@jeqo jeqo Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems there is a subtle bug here, causing the JDK17 CI failure while JDK25 passes.
configurationControl.incrementalAlterConfigs uses ControllerResult.atomicOf instead of ControllerResult.of -- trying to reproduce this locally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use ControllerResult.atomicOf, let's see how the ci goes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems all passed now.

Copy link
Copy Markdown
Contributor

@AnatolyPopov AnatolyPopov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jeqo jeqo merged commit 784dd85 into main Apr 24, 2026
7 checks passed
@jeqo jeqo deleted the giuseppelillo/fix-fetch-routing-diskless branch April 24, 2026 15:15
giuseppelillo added a commit that referenced this pull request May 6, 2026
When service fetch requests, it's necessary to discern between a topic being migrated from classic to diskless but that has not yet committed the disklessStartOffset to KRaft (in this case fetch still need to go through UnifiedLog) and a full diskless topic (fetch goes through diskless read path).
Introduce a new sentinel value (-2) for PartitionRegistration.classicToDisklessStartOffset that indicates that the partition is being migrated from classic to diskless.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants