You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by sq...@apache.org on 2026/09/30 17:41:58 UTC
(kafka) branch trunk updated: KAFKA-20292 [9/N]: Skip unchanged static members when building target assignment records (#23622)
This is an automated email from the ASF dual-hosted git repository.
squah-confluent pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git
The following commit(s) were added to refs/heads/trunk by this push:
new 0eeb5a4f308 KAFKA-20292 [9/N]: Skip unchanged static members when building target assignment records (#23622)
0eeb5a4f308 is described below
commit 0eeb5a4f3087387b7c9a8a222d5c850da14fe96a
Author: Sean Quah <sq...@confluent.io>
AuthorDate: Wed Sep 30 18:41:49 2026 +0100
KAFKA-20292 [9/N]: Skip unchanged static members when building target assignment records (#23622)
When the static members have not changed between assignor time and the
current time, we don't need to compute the static member replacements in
TargetAssignmentRecordsBuilder.
Reviewers: David Jacot <da...@apache.org>
---
.../coordinator/group/GroupMetadataManager.java | 9 +-
.../group/TargetAssignmentRecordsBuilder.java | 129 ++++++++++++---------
.../group/TargetAssignmentRecordsBuilderTest.java | 51 ++++----
.../assignor/TargetAssignmentBuilderBenchmark.java | 3 +-
4 files changed, 101 insertions(+), 91 deletions(-)
diff --git a/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/GroupMetadataManager.java b/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/GroupMetadataManager.java
index e2acc57029a..aba349c62e2 100644
--- a/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/GroupMetadataManager.java
+++ b/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/GroupMetadataManager.java
@@ -4404,8 +4404,7 @@ public class GroupMetadataManager {
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(log, group.groupId())
.withTargetAssignmentMetadata(assignmentResult.targetAssignmentMetadata())
.withCurrentMemberIds(updatedMembersAndTargetAssignment.members().keySet())
- .withPreviousStaticMembers(updatedMembersAndTargetAssignment.staticMembers())
- .withCurrentStaticMembers(updatedMembersAndTargetAssignment.staticMembers())
+ .withUnchangedStaticMembers()
.withCurrentTargetAssignment(updatedMembersAndTargetAssignment.targetAssignment())
.withNewTargetAssignment(assignmentResult.targetAssignment())
.build(records);
@@ -4495,8 +4494,7 @@ public class GroupMetadataManager {
new TargetAssignmentRecordsBuilder.ShareTargetAssignmentRecordsBuilder(log, group.groupId())
.withTargetAssignmentMetadata(assignmentResult.targetAssignmentMetadata())
.withCurrentMemberIds(updatedMembersAndTargetAssignment.members().keySet())
- .withPreviousStaticMembers(Map.of())
- .withCurrentStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentTargetAssignment(updatedMembersAndTargetAssignment.targetAssignment())
.withNewTargetAssignment(assignmentResult.targetAssignment())
.build(records);
@@ -4641,8 +4639,7 @@ public class GroupMetadataManager {
new TargetAssignmentRecordsBuilder.StreamsTargetAssignmentRecordsBuilder(log, group.groupId())
.withTargetAssignmentMetadata(assignmentResult.targetAssignmentMetadata())
.withCurrentMemberIds(updatedMembersAndTargetAssignment.members().keySet())
- .withPreviousStaticMembers(updatedMembersAndTargetAssignment.staticMembers())
- .withCurrentStaticMembers(updatedMembersAndTargetAssignment.staticMembers())
+ .withUnchangedStaticMembers()
.withCurrentTargetAssignment(updatedMembersAndTargetAssignment.targetAssignment())
.withNewTargetAssignment(assignmentResult.targetAssignment())
.build(records);
diff --git a/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilder.java b/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilder.java
index 6dfada98169..5a39f3482bf 100644
--- a/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilder.java
+++ b/group-coordinator/src/main/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilder.java
@@ -60,20 +60,28 @@ public abstract class TargetAssignmentRecordsBuilder<A> {
private TargetAssignmentMetadata targetAssignmentMetadata;
/**
- * The static members in the group at the time the new target assignment was computed.
+ * Whether the static members in the group may have changed since the new target assignment
+ * was computed.
*/
- private Map<String, String> previousStaticMembers;
+ private boolean staticMembersChanged = true;
/**
- * The current member ids in the group.
+ * The static members in the group at the time the new target assignment was computed.
+ * Only set when {@link #staticMembersChanged} is true.
*/
- private Set<String> currentMemberIds;
+ private Map<String, String> previousStaticMembers;
/**
* The current static members in the group.
+ * Only set when {@link #staticMembersChanged} is true.
*/
private Map<String, String> currentStaticMembers;
+ /**
+ * The current member ids in the group.
+ */
+ private Set<String> currentMemberIds;
+
/**
* The current target assignment.
*/
@@ -110,35 +118,43 @@ public abstract class TargetAssignmentRecordsBuilder<A> {
}
/**
- * Sets the static members in the group at the time the new target assignment was computed.
+ * Indicates that the static members in the group may have changed since the new target
+ * assignment was computed, and provides the previous and current static members so that
+ * static member replacements can be identified.
*
* @param previousStaticMembers The static members in the group at the time the new target assignment was computed.
+ * @param currentStaticMembers The current static members in the group.
* @return This object.
*/
- public TargetAssignmentRecordsBuilder<A> withPreviousStaticMembers(Map<String, String> previousStaticMembers) {
+ public TargetAssignmentRecordsBuilder<A> withChangedStaticMembers(
+ Map<String, String> previousStaticMembers,
+ Map<String, String> currentStaticMembers
+ ) {
+ this.staticMembersChanged = true;
this.previousStaticMembers = Objects.requireNonNull(previousStaticMembers);
+ this.currentStaticMembers = Objects.requireNonNull(currentStaticMembers);
return this;
}
/**
- * Sets the current member ids in the group.
+ * Indicates that the static members in the group have not changed since the new target
+ * assignment was computed, so static member replacements do not need to be identified.
*
- * @param currentMemberIds The current member ids in the group.
* @return This object.
*/
- public TargetAssignmentRecordsBuilder<A> withCurrentMemberIds(Set<String> currentMemberIds) {
- this.currentMemberIds = Objects.requireNonNull(currentMemberIds);
+ public TargetAssignmentRecordsBuilder<A> withUnchangedStaticMembers() {
+ this.staticMembersChanged = false;
return this;
}
/**
- * Sets the current static members in the group.
+ * Sets the current member ids in the group.
*
- * @param currentStaticMembers The current static members in the group.
+ * @param currentMemberIds The current member ids in the group.
* @return This object.
*/
- public TargetAssignmentRecordsBuilder<A> withCurrentStaticMembers(Map<String, String> currentStaticMembers) {
- this.currentStaticMembers = Objects.requireNonNull(currentStaticMembers);
+ public TargetAssignmentRecordsBuilder<A> withCurrentMemberIds(Set<String> currentMemberIds) {
+ this.currentMemberIds = Objects.requireNonNull(currentMemberIds);
return this;
}
@@ -184,12 +200,14 @@ public abstract class TargetAssignmentRecordsBuilder<A> {
public void build(List<CoordinatorRecord> records) {
if (targetAssignmentMetadata == null)
throw new IllegalArgumentException("Target assignment metadata must be set.");
- if (previousStaticMembers == null)
- throw new IllegalArgumentException("Previous static members must be set.");
+ if (staticMembersChanged) {
+ if (previousStaticMembers == null)
+ throw new IllegalArgumentException("Previous static members must be set.");
+ if (currentStaticMembers == null)
+ throw new IllegalArgumentException("Current static members must be set.");
+ }
if (currentMemberIds == null)
throw new IllegalArgumentException("Current member ids must be set.");
- if (currentStaticMembers == null)
- throw new IllegalArgumentException("Current static members must be set.");
if (currentTargetAssignment == null)
throw new IllegalArgumentException("Current target assignment must be set.");
if (newTargetAssignment == null)
@@ -214,49 +232,54 @@ public abstract class TargetAssignmentRecordsBuilder<A> {
// Build map of replacement member ids for static members that have churned.
Map<String, String> staticMemberIdRemapping = new HashMap<>();
- for (Map.Entry<String, String> entry : previousStaticMembers.entrySet()) {
- String instanceId = entry.getKey();
- String oldMemberId = entry.getValue();
- String newMemberId = currentStaticMembers.get(instanceId);
-
- if (currentMemberIds.contains(oldMemberId)) {
- // The old member id is still in the group. We must not create a remapping entry,
- // otherwise we could give the same assignment to two different members.
- continue;
- }
- if (newMemberId != null) {
- if (newTargetAssignment.containsKey(newMemberId)) {
- // The new member id has been in the group since before the assignment was
- // computed. We want to prioritize matching assignments up by member id, so
- // avoid creating a remapping entry. Note that we can't detect this if the
- // assignor omits an entry for the member but nothing bad happens in that case.
+ if (staticMembersChanged) {
+ for (Map.Entry<String, String> entry : previousStaticMembers.entrySet()) {
+ String instanceId = entry.getKey();
+ String oldMemberId = entry.getValue();
+ String newMemberId = currentStaticMembers.get(instanceId);
+
+ if (currentMemberIds.contains(oldMemberId)) {
+ // The old member id is still in the group. We must not create a remapping entry,
+ // otherwise we could give the same assignment to two different members.
continue;
}
- log.debug("[GroupId {}] Previous static member {} with instance id {} has been replaced by {}, transferring target assignment.",
- groupId, oldMemberId, instanceId, newMemberId);
-
- staticMemberIdRemapping.put(newMemberId, oldMemberId);
- } else {
- log.debug("[GroupId {}] Previous static member {} with instance id {} has no replacement, discarding their target assignment.",
- groupId, oldMemberId, instanceId);
+ if (newMemberId != null) {
+ if (newTargetAssignment.containsKey(newMemberId)) {
+ // The new member id has been in the group since before the assignment was
+ // computed. We want to prioritize matching assignments up by member id, so
+ // avoid creating a remapping entry. Note that we can't detect this if the
+ // assignor omits an entry for the member but nothing bad happens in that case.
+ continue;
+ }
+
+ log.debug("[GroupId {}] Previous static member {} with instance id {} has been replaced by {}, transferring target assignment.",
+ groupId, oldMemberId, instanceId, newMemberId);
+
+ staticMemberIdRemapping.put(newMemberId, oldMemberId);
+ } else {
+ log.debug("[GroupId {}] Previous static member {} with instance id {} has no replacement, discarding their target assignment.",
+ groupId, oldMemberId, instanceId);
+ }
}
}
if (log.isDebugEnabled()) {
- for (Map.Entry<String, String> entry : currentStaticMembers.entrySet()) {
- String instanceId = entry.getKey();
- String newMemberId = entry.getValue();
-
- if (newTargetAssignment.containsKey(newMemberId)) {
- // The member id has been in the group the whole time.
- continue;
- }
-
- if (!previousStaticMembers.containsKey(instanceId)) {
- log.debug("[GroupId {}] Current static member {} with instance id {} has no previous static member and will receive an empty target assignment.",
- groupId, newMemberId, instanceId);
+ if (staticMembersChanged) {
+ for (Map.Entry<String, String> entry : currentStaticMembers.entrySet()) {
+ String instanceId = entry.getKey();
+ String newMemberId = entry.getValue();
+
+ if (newTargetAssignment.containsKey(newMemberId)) {
+ // The member id has been in the group the whole time.
+ continue;
+ }
+
+ if (!previousStaticMembers.containsKey(instanceId)) {
+ log.debug("[GroupId {}] Current static member {} with instance id {} has no previous static member and will receive an empty target assignment.",
+ groupId, newMemberId, instanceId);
+ }
}
}
diff --git a/group-coordinator/src/test/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilderTest.java b/group-coordinator/src/test/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilderTest.java
index c64411adba5..3559ec1d7a0 100644
--- a/group-coordinator/src/test/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilderTest.java
+++ b/group-coordinator/src/test/java/org/apache/kafka/coordinator/group/TargetAssignmentRecordsBuilderTest.java
@@ -48,9 +48,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of())
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of())
.withNewTargetAssignment(Map.of())
.build();
@@ -68,9 +67,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1", "member-2"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
mkTopicAssignment(fooTopicId, 0, 1, 2),
@@ -106,9 +104,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1", "member-2"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
mkTopicAssignment(fooTopicId, 0, 1, 2),
@@ -154,9 +151,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1", "member-2", "member-3"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
mkTopicAssignment(fooTopicId, 0, 1),
@@ -208,9 +204,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of())
// The assignor did not include an entry for member 1.
.withNewTargetAssignment(Map.of())
@@ -231,9 +226,8 @@ public class TargetAssignmentRecordsBuilderTest {
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
// Member 2 has left.
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
mkTopicAssignment(topicId, 0, 1, 2, 3)
@@ -268,9 +262,8 @@ public class TargetAssignmentRecordsBuilderTest {
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
// Member 2 has joined.
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1", "member-2"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
mkTopicAssignment(topicId, 0, 1, 2)
@@ -298,9 +291,11 @@ public class TargetAssignmentRecordsBuilderTest {
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
// Static member 2 has been replaced with member 3.
- .withPreviousStaticMembers(Map.of("instance-id", "member-2"))
+ .withChangedStaticMembers(
+ Map.of("instance-id", "member-2"),
+ Map.of("instance-id", "member-3")
+ )
.withCurrentMemberIds(Set.of("member-1", "member-3"))
- .withCurrentStaticMembers(Map.of("instance-id", "member-3"))
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
mkTopicAssignment(topicId, 0, 1, 2)
@@ -343,9 +338,11 @@ public class TargetAssignmentRecordsBuilderTest {
// member id 1 has been around the whole time and member id 2 is new.
// instance-id-2 has "moved" from member id 3 to member id 4.
// member id 3 left and member id 4 has been around the whole time.
- .withPreviousStaticMembers(Map.of("instance-id-1", "member-1", "instance-id-2", "member-3"))
+ .withChangedStaticMembers(
+ Map.of("instance-id-1", "member-1", "instance-id-2", "member-3"),
+ Map.of("instance-id-1", "member-2", "instance-id-2", "member-4")
+ )
.withCurrentMemberIds(Set.of("member-1", "member-2", "member-4"))
- .withCurrentStaticMembers(Map.of("instance-id-1", "member-2", "instance-id-2", "member-4"))
.withCurrentTargetAssignment(Map.of())
.withNewTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(
@@ -387,9 +384,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of())
.withNewTargetAssignment(Map.of())
.build();
@@ -408,9 +404,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(mkTopicAssignment(topicId, 0)))
))
@@ -436,9 +431,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ShareTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of())
.withNewTargetAssignment(Map.of())
.build();
@@ -457,9 +451,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.ShareTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", new Assignment(mkAssignment(mkTopicAssignment(topicId, 0, 1)))
))
@@ -485,9 +478,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.StreamsTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of())
.withNewTargetAssignment(Map.of())
.build();
@@ -506,9 +498,8 @@ public class TargetAssignmentRecordsBuilderTest {
List<CoordinatorRecord> records =
new TargetAssignmentRecordsBuilder.StreamsTargetAssignmentRecordsBuilder(LOG, "my-group")
.withTargetAssignmentMetadata(new TargetAssignmentMetadata(20, 12345L))
- .withPreviousStaticMembers(Map.of())
+ .withUnchangedStaticMembers()
.withCurrentMemberIds(Set.of("member-1"))
- .withCurrentStaticMembers(Map.of())
.withCurrentTargetAssignment(Map.of(
"member-1", mkTasksTuple(TaskRole.ACTIVE,
mkTasks(subtopology1, 0)
diff --git a/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/assignor/TargetAssignmentBuilderBenchmark.java b/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/assignor/TargetAssignmentBuilderBenchmark.java
index 8054e725ff2..c7e62d35d75 100644
--- a/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/assignor/TargetAssignmentBuilderBenchmark.java
+++ b/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/assignor/TargetAssignmentBuilderBenchmark.java
@@ -137,8 +137,7 @@ public class TargetAssignmentBuilderBenchmark {
targetAssignmentRecordsBuilder =
new TargetAssignmentRecordsBuilder.ConsumerTargetAssignmentRecordsBuilder(LOG, GROUP_ID)
.withCurrentMemberIds(updatedMembersAndTargetAssignment.members().keySet())
- .withPreviousStaticMembers(updatedMembersAndTargetAssignment.staticMembers())
- .withCurrentStaticMembers(updatedMembersAndTargetAssignment.staticMembers())
+ .withUnchangedStaticMembers()
.withCurrentTargetAssignment(updatedMembersAndTargetAssignment.targetAssignment());
}