-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-13888: Addition of Information in DescribeQuorumResponse #12508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
c5b4323
19af2c2
ddbfbea
0d70f91
73e034e
5de54cd
9322538
36f4f75
8630b3f
b1c2b1e
9a55624
8a105d2
0d79978
b00e66c
a12013c
02dc7ad
d1936ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -804,28 +804,24 @@ class KRaftClusterTest { | |
| val quorumState = admin.describeMetadataQuorum(new DescribeMetadataQuorumOptions) | ||
| val quorumInfo = quorumState.quorumInfo.get() | ||
|
|
||
| assertEquals(4, quorumInfo.observers.size) | ||
| assertEquals(3, quorumInfo.voters.size) | ||
| assertEquals(cluster.controllers.asScala.keySet, quorumInfo.voters.asScala.map(_.replicaId).toSet) | ||
| assertTrue(2999 < quorumInfo.leaderId && 3003 > quorumInfo.leaderId, | ||
| s"Leader ID ${quorumInfo.leaderId} was not within expected range.") | ||
|
|
||
| quorumInfo.observers.forEach { observer => | ||
| assertTrue(-1 < observer.replicaId && 4 > observer.replicaId, | ||
| s"Observer ID ${observer.replicaId} was not within expected range.") | ||
| assertTrue(0 < observer.logEndOffset, | ||
| s"logEndOffset for observer with ID ${observer.replicaId} was ${observer.logEndOffset}") | ||
| assertNotEquals(OptionalLong.empty(), observer.lastFetchTimeMs) | ||
| assertNotEquals(OptionalLong.empty(), observer.lastCaughtUpTimeMs) | ||
| } | ||
|
|
||
| quorumInfo.voters.forEach { voter => | ||
| assertTrue(2999 < voter.replicaId && 3003 > voter.replicaId, | ||
| s"Voter ID ${voter.replicaId} was not within expected range.") | ||
| assertTrue(0 < voter.logEndOffset, | ||
| s"logEndOffset for voter with ID ${voter.replicaId} was ${voter.logEndOffset}") | ||
| assertNotEquals(OptionalLong.empty(), voter.lastFetchTimeMs) | ||
| assertNotEquals(OptionalLong.empty(), voter.lastCaughtUpTimeMs) | ||
| } | ||
|
|
||
| assertEquals(cluster.brokers.asScala.keySet, quorumInfo.observers.asScala.map(_.replicaId).toSet) | ||
| quorumInfo.observers.forEach { observer => | ||
| assertTrue(0 < observer.logEndOffset, | ||
| s"logEndOffset for observer with ID ${observer.replicaId} was ${observer.logEndOffset}") | ||
| assertNotEquals(OptionalLong.empty(), observer.lastFetchTimeMs) | ||
| assertNotEquals(OptionalLong.empty(), observer.lastCaughtUpTimeMs) | ||
| } | ||
| } catch { | ||
| case _: InvalidRequestException => log.error("Hit Kafka-13490. Claim test succeeded") | ||
| case t: Throwable => throw t | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: if we're just re-throwing, we don't need to catch |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,6 @@ | |
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import java.util.OptionalInt; | ||
| import java.util.OptionalLong; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
@@ -208,7 +207,7 @@ private boolean updateHighWatermark() { | |
| /** | ||
| * Update the local replica state. | ||
| * | ||
| * See {@link #updateReplicaState(int, long, LogOffsetMetadata, Long)} | ||
| * See {@link #updateReplicaState(int, long, LogOffsetMetadata, long)} | ||
| */ | ||
| public boolean updateLocalState(long fetchTimestamp, LogOffsetMetadata logOffsetMetadata) { | ||
| return updateReplicaState(localId, fetchTimestamp, logOffsetMetadata, logOffsetMetadata.offset); | ||
|
|
@@ -224,10 +223,10 @@ public boolean updateLocalState(long fetchTimestamp, LogOffsetMetadata logOffset | |
| * @return true if the high watermark is updated too | ||
| */ | ||
| public boolean updateReplicaState( | ||
| int replicaId, | ||
| long fetchTimestamp, | ||
| LogOffsetMetadata logOffsetMetadata, | ||
| Long leaderLogEndOffset | ||
| int replicaId, | ||
| long fetchTimestamp, | ||
| LogOffsetMetadata logOffsetMetadata, | ||
| long leaderLogEndOffset | ||
| ) { | ||
| // Ignore fetches from negative replica id, as it indicates | ||
| // the fetch is from non-replica. For example, a consumer. | ||
|
|
@@ -266,8 +265,8 @@ private List<ReplicaState> followersByDescendingFetchOffset() { | |
| } | ||
|
|
||
| private void verifyEndOffsetUpdate( | ||
| ReplicaState state, | ||
| LogOffsetMetadata endOffsetMetadata | ||
| ReplicaState state, | ||
| LogOffsetMetadata endOffsetMetadata | ||
| ) { | ||
| state.endOffset.ifPresent(currentEndOffset -> { | ||
| if (currentEndOffset.offset > endOffsetMetadata.offset) { | ||
|
|
@@ -282,9 +281,9 @@ private void verifyEndOffsetUpdate( | |
| }); | ||
| } | ||
| private boolean updateEndOffset( | ||
| ReplicaState state, | ||
| LogOffsetMetadata endOffsetMetadata, | ||
| boolean verifyUpdate | ||
| ReplicaState state, | ||
| LogOffsetMetadata endOffsetMetadata, | ||
| boolean verifyUpdate | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this? Seems like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wanted to retain the verification step in the method in case we want to use it elsewhere in the future. |
||
| ) { | ||
| if (verifyUpdate) { | ||
| verifyEndOffsetUpdate(state, endOffsetMetadata); | ||
|
|
@@ -320,22 +319,23 @@ private ReplicaState getReplicaState(int remoteNodeId) { | |
| } | ||
|
|
||
| List<DescribeQuorumResponseData.ReplicaState> quorumResponseVoterStates(long currentTimeMs) { | ||
| return quorumResponseReplicaStates(voterStates.values(), OptionalInt.of(localId), currentTimeMs); | ||
| return quorumResponseReplicaStates(voterStates.values(), localId, currentTimeMs); | ||
| } | ||
|
|
||
| List<DescribeQuorumResponseData.ReplicaState> quorumResponseObserverStates(long currentTimeMs) { | ||
| clearInactiveObservers(currentTimeMs); | ||
| return quorumResponseReplicaStates(observerStates.values(), OptionalInt.empty(), currentTimeMs); | ||
| return quorumResponseReplicaStates(observerStates.values(), localId, currentTimeMs); | ||
| } | ||
|
|
||
| private static <R extends ReplicaState> List<DescribeQuorumResponseData.ReplicaState> quorumResponseReplicaStates( | ||
| Collection<R> state, | ||
| OptionalInt leaderId, | ||
| long currentTimeMs) { | ||
| private static List<DescribeQuorumResponseData.ReplicaState> quorumResponseReplicaStates( | ||
| Collection<ReplicaState> state, | ||
| int leaderId, | ||
| long currentTimeMs | ||
| ) { | ||
| return state.stream().map(s -> { | ||
| final long lastCaughtUpTimestamp; | ||
| final long lastFetchTimestamp; | ||
| if (s.nodeId == leaderId.orElse(-1)) { | ||
| if (s.nodeId == leaderId) { | ||
| lastCaughtUpTimestamp = currentTimeMs; | ||
| lastFetchTimestamp = currentTimeMs; | ||
| } else { | ||
|
|
@@ -407,7 +407,7 @@ else if (!that.endOffset.isPresent()) | |
| public String toString() { | ||
| return String.format( | ||
| "ReplicaState(nodeId=%d, endOffset=%s, lastFetchTimestamp=%s, " + | ||
| " lastCaughtUpTimestamp=%s, hasAcknowledgedLeader=%s)", | ||
| "lastCaughtUpTimestamp=%s, hasAcknowledgedLeader=%s)", | ||
| nodeId, | ||
| endOffset, | ||
| lastFetchTimestamp, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could make this assertion a little more generic by asserting that
quorumInfo.leaderIdis contained incluster.controllers.asScala.keySet.