splett2 commented on code in PR #19296:
URL: https://github.com/apache/kafka/pull/19296#discussion_r2017080238
##########
metadata/src/test/java/org/apache/kafka/controller/ClusterControlManagerTest.java:
##########
@@ -978,6 +980,129 @@ public void
testBrokerContactTimesAreUpdatedOnClusterControlActivation() {
contactTime(new BrokerIdAndEpoch(2, 100)));
}
+ @Test
+ public void testDuplicateBrokerRegistrationWithActiveOldBroker() {
+ // active here means brokerHeartbeatManager last recorded the broker
as unfenced and not in controlled shutdown
+ long brokerSessionTimeoutMs = 1000;
+ MockTime time = new MockTime(0L, 20L, 1000L);
+ FinalizedControllerFeatures finalizedFeatures = new
FinalizedControllerFeatures(
+ Map.of(MetadataVersion.FEATURE_NAME,
MetadataVersion.LATEST_PRODUCTION.featureLevel()), 456L);
+ ClusterControlManager clusterControl = new
ClusterControlManager.Builder().
+ setClusterId("pjvUwj3ZTEeSVQmUiH3IJw").
+ setFeatureControlManager(createFeatureControlManager()).
+ setBrokerShutdownHandler((brokerId, isCleanShutdown, records) -> {
}).
+
setSessionTimeoutNs(TimeUnit.MILLISECONDS.toNanos(brokerSessionTimeoutMs)).
+ setTime(time).
+ build();
+ clusterControl.replay(new RegisterBrokerRecord().
+ setBrokerEpoch(100).
+ setBrokerId(0).
+ setLogDirs(List.of(Uuid.fromString("Mj3CW3OSRi29cFeNJlXuAQ"))).
+ setFenced(false), 10002);
+ clusterControl.activate();
+ assertEquals(OptionalLong.of(1000L),
clusterControl.heartbeatManager().tracker().
+ contactTime(new BrokerIdAndEpoch(0, 100)));
+
+ // while session is still valid for old broker, duplicate requests
should fail
+ time.sleep(brokerSessionTimeoutMs / 2);
+ assertThrows(DuplicateBrokerRegistrationException.class, () ->
+ clusterControl.registerBroker(new BrokerRegistrationRequestData().
+ setClusterId("pjvUwj3ZTEeSVQmUiH3IJw").
+ setBrokerId(0).
+
setLogDirs(List.of(Uuid.fromString("TyNK6XSSQJaJc2q9uflNHg"))).
+ setFeatures(new
BrokerRegistrationRequestData.FeatureCollection(
+ Set.of(new BrokerRegistrationRequestData.Feature().
+ setName(MetadataVersion.FEATURE_NAME).
+
setMinSupportedVersion(MetadataVersion.MINIMUM_VERSION.featureLevel()).
+
setMaxSupportedVersion(MetadataVersion.LATEST_PRODUCTION.featureLevel())).iterator())).
+ setIncarnationId(Uuid.fromString("0H4fUu1xQEKXFYwB1aBjhg")),
+ 101L,
+ finalizedFeatures,
+ false));
+
+ // if session expires for broker, even if the broker was active the
new registration will succeed
+ time.sleep(brokerSessionTimeoutMs);
+ clusterControl.registerBroker(new BrokerRegistrationRequestData().
+ setClusterId("pjvUwj3ZTEeSVQmUiH3IJw").
+ setBrokerId(0).
+ setLogDirs(List.of(Uuid.fromString("TyNK6XSSQJaJc2q9uflNHg"))).
+ setFeatures(new
BrokerRegistrationRequestData.FeatureCollection(
+ Set.of(new BrokerRegistrationRequestData.Feature().
+ setName(MetadataVersion.FEATURE_NAME).
+
setMinSupportedVersion(MetadataVersion.MINIMUM_VERSION.featureLevel()).
+
setMaxSupportedVersion(MetadataVersion.LATEST_PRODUCTION.featureLevel())).iterator())).
+ setIncarnationId(Uuid.fromString("0H4fUu1xQEKXFYwB1aBjhg")),
+ 101L,
+ finalizedFeatures,
+ false);
+ }
+
+ @Test
+ public void testDuplicateBrokerRegistrationWithInactiveBroker() {
+ // inactive here means brokerHeartbeatManager last recorded the broker
as fenced or in controlled shutdown
+ long brokerSessionTimeoutMs = 1000;
+ MockTime time = new MockTime(0L, 20L, 1000L);
+ FinalizedControllerFeatures finalizedFeatures = new
FinalizedControllerFeatures(
+ Map.of(MetadataVersion.FEATURE_NAME,
MetadataVersion.LATEST_PRODUCTION.featureLevel()), 456L);
+ ClusterControlManager clusterControl = new
ClusterControlManager.Builder().
+ setClusterId("pjvUwj3ZTEeSVQmUiH3IJw").
+ setFeatureControlManager(createFeatureControlManager()).
+ setBrokerShutdownHandler((brokerId, isCleanShutdown, records) -> {
}).
+
setSessionTimeoutNs(TimeUnit.MILLISECONDS.toNanos(brokerSessionTimeoutMs)).
+ setTime(time).
+ build();
+ // first broker is fenced
+ clusterControl.replay(new RegisterBrokerRecord().
+ setBrokerEpoch(100).
+ setBrokerId(0).
+ setLogDirs(List.of(Uuid.fromString("Mj3CW3OSRi29cFeNJlXuAQ"))).
+ setFenced(true).
+ setInControlledShutdown(false), 10002);
+ // second broker is in controlled shutdown
+ clusterControl.replay(new RegisterBrokerRecord().
+ setBrokerEpoch(200).
+ setBrokerId(1).
+ setLogDirs(List.of(Uuid.fromString("TyNK6XSSQJaJc2q9uflNHg"))).
+ setFenced(false).
+ setInControlledShutdown(true), 20002);
+ clusterControl.activate();
+
clusterControl.heartbeatManager().maybeUpdateControlledShutdownOffset(1, 20002);
+
+ assertEquals(OptionalLong.of(1000L),
clusterControl.heartbeatManager().tracker().
+ contactTime(new BrokerIdAndEpoch(0, 100)));
+ assertEquals(OptionalLong.of(1000L),
clusterControl.heartbeatManager().tracker().
+ contactTime(new BrokerIdAndEpoch(1, 200)));
+
+ // even if session is still valid for old brokers, new registrations
will succeed
Review Comment:
nit: I think the wording here should be something along the lines of:
> new registrations should succeed if a broker is fenced or in controlled
shutdown, even if the last heartbeat was within the session timeout
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]