Skip to content

KAFKA-20790: add AssignmentConfigs interface - #23092

Merged
mjsax merged 18 commits into
apache:trunkfrom
gabriellefu:assignmentconfig
Aug 12, 2026
Merged

KAFKA-20790: add AssignmentConfigs interface#23092
mjsax merged 18 commits into
apache:trunkfrom
gabriellefu:assignmentconfig

Conversation

@gabriellefu

@gabriellefu gabriellefu commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Adding AssignmentConfigs a public API for KIP-1357.

Reviewers: Sean Quah squah@confluent.io, Matthias J. Sax
matthias@confluent.io

@github-actions github-actions Bot removed the triage PRs from the community label Aug 7, 2026

@squah-confluent squah-confluent left a comment

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.

Thanks for updating the PR!

/**
* The configs used for a group that has none of them set.
*/
public static final AssignmentConfigsImpl DEFAULT = new AssignmentConfigsImpl(0, List.of());

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.

Where do we plan to define the default num.standby.replicas and rack.aware.assignment.tags? Can we have a single source of truth for the defaults?

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 added AssignmentConfigsImpl.DEFAULT which is the default value of all the single config in the configs(), and also added some helper to construct AssignmentConfigsImpl with all default value except certain configs


GroupAssignment result = assignor.assign(
new GroupSpecImpl(members, mkMap(mkEntry(NUM_STANDBY_REPLICAS_CONFIG, String.valueOf(numStandbyReplicas)))),
new GroupSpecImpl(members, new AssignmentConfigsImpl(numStandbyReplicas, List.of())),

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.

These constructor calls are still going to be annoying to update when we add new configs.
We could leave them be or we could try to tidy things up some more, for example, by adding helper methods to construct an AssignmentConfigsImpl with default values but a specific num.standby.replicas or rack.aware.assignment.tags (eg. a withNumStandbyReplicas)

(Only applies to calls where we would want to take the defaults for future configs.)

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 have another pr is to avoid epoch bump when there's new config being introduced. So I was thinking about implement the default part maybe after this pr is merged? #23088

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 can close the other pr and put the change in this pr too

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.

hm I think the not-bumping logic belongs in separate PR. Maybe we could bring the constant definition forward? But I don't really mind as long as the final state is clean.

How do you imagine these new AssignmentConfigsImpl calls to look at the end of it all?

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.

sounds good, i can do that. In the tests we can only pass the configs we actually care about , otherwise they will use there default value, for replicas is 0 and for tag is "".

public static final AssignmentConfigsImpl DEFAULT = new AssignmentConfigsImpl(
GroupCoordinatorConfig.STREAMS_GROUP_NUM_STANDBY_REPLICAS_DEFAULT,
// The parsed form of STREAMS_GROUP_RACK_AWARE_ASSIGNMENT_TAGS_DEFAULT, which ConfigDef spells as "".
List.of()

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 default of "rack.aware.assignment.tags" is "", and if we directly parse it into a List, it will give a [""] instead of a empty list [], so we still hardcode the default here

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.

Hmmm... This still seems to be error prone? In the end, we should have a single source of truth... Should we rather use STREAMS_GROUP_RACK_AWARE_ASSIGNMENT_TAGS_DEFAULT and parse it into empty List? If the default changes, this code would update immediatly?

But on the other hand, it seem we are using DEFAULT only in tests, what make it somewhat questionable, if it's the right place to add it here?

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 also use DEFAULT in fromMap(), if the config is a empty map, it returns DEFAULT otherwise it parse the config. But I agree with the STREAMS_GROUP_RACK_AWARE_ASSIGNMENT_TAGS_DEFAULT part I will update accordingly.

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 have added a helper here to parse STREAMS_GROUP_RACK_AWARE_ASSIGNMENT_TAGS_DEFAULT

// ConfigDef has already validated to be non-empty and free of surrounding whitespace.
String rackAwareAssignmentTags = configs.get(RACK_AWARE_ASSIGNMENT_TAGS_CONFIG);
return new AssignmentConfigsImpl(
Integer.parseInt(configs.get(NUM_STANDBY_REPLICAS_CONFIG)),

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.

Don't we need null check here and translate it to 0 ?

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.

In the original code, for replicas, there are two path, one is the whole map is empty, then it's ok to not having replicas set and here we return DEFAULT, other than that, the replicas should always be in the config

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.

Ok. Seems we are scattered logic, making it hard to reason about this... No critical for 4.4 release, but wondering if we could do a follow up cleanup PR, streamlining this a little bit better to make it easier as a (human 🤣) reviewer to follow...

Maybe we should "unify" the raw Map<String, String> and AssignmentConfigsImpl somehow, to have a single object we use and pass around, an avoid converting the one into the other multiple times along the way, at different places.

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.

I have a similar question here. Maybe we could leverage the default value?

String numStandby = configs.getOrDefault(
    NUM_STANDBY_REPLICAS_CONFIG, 
    String.valueOf(GroupCoordinatorConfig.STREAMS_GROUP_NUM_STANDBY_REPLICAS_DEFAULT)
);

return new AssignmentConfigsImpl(
    Integer.parseInt(numStandby),
    parseRackAwareAssignmentTags(rackAwareAssignmentTags)
);

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.

have updated in this following pr:#23165 thanks

* parses a {@code LIST} configuration: an empty value is an empty list, not a list holding an empty string.
*/
private static List<String> parseRackAwareAssignmentTags(String rackAwareAssignmentTags) {
return rackAwareAssignmentTags.isEmpty() ? List.of() : List.of(rackAwareAssignmentTags.split(","));

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.

isEmpty() checks for length() == 0, right? What about " " (or similar). Do we need to to do rackAwareAssignmentTags.trim().isEmpty()` ?

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 input of this will be the output of String.join(",", tags), in this case, there won't be " ". But I do feel like here the type has been a bit confusing, I will submit a follow up pr to clean up those things

@mjsax mjsax added streams kip Requires or implements a KIP labels Aug 11, 2026

@squah-confluent squah-confluent left a comment

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.

Thanks, looks good!

public class AssignmentConfigsImplTest {

@Test
void testDefaultHoldsTheDefaultOfEveryConfig() {

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.

nit: I'd just call this testDefault.

}

@Test
void testWithersLeaveTheOtherConfigsUntouched() {

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.

nit: I'd just call this testWithers

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.

have changed! thanks

gabriellefu and others added 2 commits August 12, 2026 11:53
Resolves conflicts with KAFKA-20719 (apache#22783): keep the taskOffsets
benchmark plumbing from trunk and the AssignmentConfigs API from this
branch; convert the new StickyTaskAssignorTest cases to
AssignmentConfigsImpl.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@squah-confluent squah-confluent left a comment

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.

Thanks!

@mjsax
mjsax merged commit 89a6c9e into apache:trunk Aug 12, 2026
20 checks passed
mjsax pushed a commit that referenced this pull request Aug 12, 2026
Adding AssignmentConfigs a public API for KIP-1357.

Reviewers: Sean Quah <squah@confluent.io>, Matthias J. Sax
 <matthias@confluent.io>
@mjsax

mjsax commented Aug 12, 2026

Copy link
Copy Markdown
Member

Merged to trunk and cherry-picked to 4.4 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants