Skip to content

MINOR: Make share group state partition metadata unmodifiable - #23888

Merged
squah-confluent merged 5 commits into
apache:trunkfrom
confluentinc:squah-immutable-initmapvalue-and-refactor
Oct 21, 2026
Merged

squah-confluent merged 5 commits into
apache:trunkfrom
confluentinc:squah-immutable-initmapvalue-and-refactor

Conversation

@squah-confluent

@squah-confluent squah-confluent commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Wrap InitMapValue's partitions and
ShareGroupStatePartitionMetadataInfo's collections in unmodifiable
views, so that the share group state partition metadata cannot be
modified through them. Add withAddedPartitions and withRemovedPartitions
to InitMapValue to derive new values.

Use them in GroupMetadataManager and remove the copies that are no
longer needed. combineInitMaps reuses a value when only one of the maps
has the topic, and initializeShareGroupState no longer deep copies the
initializing topics to remove partitions in place.
initializedShareGroupPartitions and
sharePartitionsEligibleForOffsetDeletion no longer copy the partitions.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

Reviewers: David Jacot dajac@apache.org

InitMapValue now copies its partitions with Set.copyOf, so that the
share group state partition metadata can be shared without defensive
copies, such as with assignors offloaded to another thread. Add
withAddedPartitions and withRemovedPartitions to derive new values, and
a constructor taking a Collection for the partition lists in records.

Use them in GroupMetadataManager and remove the copies that are no
longer needed. combineInitMaps reuses a value when only one of the maps
has the topic, and initializeShareGroupState no longer deep copies the
initializing topics to remove partitions in place.
initializedShareGroupPartitions and sharePartitionsEligibleForOffsetDeletion
no longer copy the partitions.

The partitions of the immutable sets are iterated in an unspecified
order, so tests now compare them regardless of order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added triage PRs from the community group-coordinator labels Oct 20, 2026
Comment on lines 82 to 87
public record ShareGroupStatePartitionMetadataInfo(
Map<Uuid, InitMapValue> initializingTopics,
Map<Uuid, InitMapValue> initializedTopics,
Set<Uuid> deletingTopics
) {
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

While we are here, should we ensure that the two Maps and the Set are immutable too?

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.

Yes, we can do that too

Comment on lines +115 to +117
Set<Integer> newPartitions = new HashSet<>(partitions);
newPartitions.addAll(added);
return new InitMapValue(name, newPartitions, timestamp);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is a tad wasteful to allocate an HashSet here to then copy it in InitMapValue. Have you considered using unmodifiableSet?

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.

Do you mean replacing Set.copyOf with Collections.unmodifiableSet in the constructor or passing an unmodifiableSet wrapper in to the existing constructor?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Either way is fine. I don't really have a preference and I don't think that we have established a pattern (yet).

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.

I prefer copyOf in the constructor since it's truly immutable and it's not possible to misuse by holding on to the original collection and modifying it. But it does end up with more copies overall.

I think our original convention was to use Collections.unmodifiableMap/Set in constructors, so I'll go with that. Though the streams code is pulling a different way and going with copyOf lately...

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.

The current version of the PR uses unmodifiableMap/Set.

Comment on lines +125 to +127
Set<Integer> newPartitions = new HashSet<>(partitions);
newPartitions.removeAll(removed);
return new InitMapValue(name, newPartitions, timestamp);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ditto.

@airlock-confluentinc
airlock-confluentinc Bot force-pushed the squah-immutable-initmapvalue-and-refactor branch 2 times, most recently from c461d8c to 088c095 Compare October 21, 2026 10:59
@squah-confluent squah-confluent changed the title MINOR: Make InitMapValue's partitions immutable MINOR: Make share group state partition metadata unmodifiable Oct 21, 2026
@github-actions github-actions Bot added the small Small PRs label Oct 21, 2026
squah-confluent and others added 2 commits October 21, 2026 12:37
…of copying them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fiable

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* @param added The partitions to add.
* @return A copy of this value with the partitions added.
*/
public InitMapValue withAddedPartitions(Collection<Integer> added) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We always use it with Set. I wonder if we should directly use it here too.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to unit tests those new methods?

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.

We always use it with Set. I wonder if we should directly use it here too.

Yes, we can take Sets.

Do we need to unit tests those new methods?

Yes, those do need some basic tests. Added unit tests

* @param removed The partitions to remove.
* @return A copy of this value with the partitions removed.
*/
public InitMapValue withRemovedPartitions(Collection<Integer> removed) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ditto.

squah-confluent and others added 2 commits October 21, 2026 14:54
…edPartitions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the small Small PRs label Oct 21, 2026

@dajac dajac left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@squah-confluent
squah-confluent merged commit 8b5fc1b into apache:trunk Oct 21, 2026
23 checks passed
@squah-confluent
squah-confluent deleted the squah-immutable-initmapvalue-and-refactor branch October 21, 2026 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants