diff --git a/raft/src/main/java/org/apache/kafka/raft/QuorumState.java b/raft/src/main/java/org/apache/kafka/raft/QuorumState.java index 4ae24c84eaf99..3bf46b141c65f 100644 --- a/raft/src/main/java/org/apache/kafka/raft/QuorumState.java +++ b/raft/src/main/java/org/apache/kafka/raft/QuorumState.java @@ -379,7 +379,7 @@ public void transitionToResigned(List preferredSuccessors) { */ public void transitionToUnattached(int epoch, OptionalInt leaderId) { int currentEpoch = state.epoch(); - if (epoch < currentEpoch || (epoch == currentEpoch && !isProspective())) { + if (epoch < currentEpoch || (epoch == currentEpoch && (!isProspective() || isResigned()))) { throw new IllegalStateException( String.format( "Cannot transition to Unattached with epoch %d from current state %s", @@ -574,6 +574,14 @@ public void transitionToFollower(int epoch, int leaderId, Endpoints endpoints) { state ) ); + } else if (isResigned()) { + throw new IllegalStateException( + String.format( + "Cannot transition to Follower within same epoch %s from state %s", + epoch, + state + ) + ); } } diff --git a/raft/src/test/java/org/apache/kafka/raft/QuorumStateTest.java b/raft/src/test/java/org/apache/kafka/raft/QuorumStateTest.java index 76d942d2bd98b..dbc3f56825d06 100644 --- a/raft/src/test/java/org/apache/kafka/raft/QuorumStateTest.java +++ b/raft/src/test/java/org/apache/kafka/raft/QuorumStateTest.java @@ -2506,7 +2506,6 @@ public void testLeaderToAnyStateLowerEpoch(KRaftVersion kraftVersion) { /** * Test transitions from Resigned */ - // KAFKA-18379 to fill in the rest of the cases @ParameterizedTest @EnumSource(value = KRaftVersion.class) public void testResignedToFollowerInSameEpoch(KRaftVersion kraftVersion) { @@ -2520,8 +2519,7 @@ public void testResignedToFollowerInSameEpoch(KRaftVersion kraftVersion) { state.initialize(new OffsetAndEpoch(0L, logEndEpoch)); assertTrue(state.isResigned()); assertThrows(IllegalStateException.class, () -> state.transitionToFollower(epoch, localId, voters.listeners(localId))); - // KAFKA-18379 will fix this - state.transitionToFollower(epoch, node1, voters.listeners(node1)); + assertThrows(IllegalStateException.class, () -> state.transitionToFollower(epoch, node1, voters.listeners(node1))); } @ParameterizedTest