@@ -2207,6 +2207,40 @@ private boolean handleFetchSnapshotResponse(
22072207 return true ;
22082208 }
22092209
2210+ /**
2211+ * Handle a AddVoter request. This API is used to dynamically add a new voter
2212+ * to the quorum. The request must be sent to the current quorum leader, and will
2213+ * only succeed if the leader has committed its current epoch and HWM.
2214+ *
2215+ * The request may include an optional clusterId. If provided, it must match this
2216+ * cluster's id, otherwise the request will be rejected.
2217+ *
2218+ * The new voter is validated against the current voter set. If the voter is already
2219+ * present, or if the request does not include a valid voter id or endpoint, the
2220+ * request will fail immediately.
2221+ *
2222+ * When valid, the leader tentatively adds the new voter and sends it an ApiVersions
2223+ * request to verify protocol compatibility. This is an asynchronous step:
2224+ * the ApiVersionsResponse will later be handled in {@link #handleApiVersionsResponse},
2225+ * where the leader decides whether to keep the voter (if compatible) or remove it
2226+ * again (if incompatible or unreachable).
2227+ *
2228+ * This API may return the following errors:
2229+ *
2230+ * - {@link Errors#INCONSISTENT_CLUSTER_ID} if the cluster id is provided but does
2231+ * not match this cluster's id
2232+ * - {@link Errors#FENCED_LEADER_EPOCH} if the epoch is smaller than this node's epoch
2233+ * - {@link Errors#UNKNOWN_LEADER_EPOCH} if the epoch is larger than this node's epoch
2234+ * - {@link Errors#NOT_LEADER_OR_FOLLOWER} if the request was sent to a broker that
2235+ * is not the current quorum leader
2236+ * - {@link Errors#BROKER_NOT_AVAILABLE} if this node is currently shutting down
2237+ * - {@link Errors#REQUEST_TIMED_OUT} if the leader is still processing a previous
2238+ * voter change, or if the high watermark has not yet advanced
2239+ * - {@link Errors#DUPLICATE_VOTER} if the requested voter id already exists in the
2240+ * current voter set
2241+ * - {@link Errors#UNSUPPORTED_VERSION} if the cluster does not support kraft.version 1
2242+ * - {@link Errors#INVALID_REQUEST} if the request does not include a valid voter or endpoint
2243+ */
22102244 private CompletableFuture <AddRaftVoterResponseData > handleAddVoterRequest (
22112245 RaftRequest .Inbound requestMetadata ,
22122246 long currentTimeMs
@@ -2310,6 +2344,42 @@ private boolean handleAddVoterResponse(
23102344 }
23112345 }
23122346
2347+ /**
2348+ * Handle a RemoveVoter request. This API is used to dynamically remove an existing
2349+ * voter from the quorum. The request must be sent to the current quorum leader,
2350+ * and will only succeed if the leader has committed its current epoch and HWM.
2351+ *
2352+ * The request may include an optional clusterId. If provided, it must match this
2353+ * cluster's id, otherwise the request will be rejected.
2354+ *
2355+ * The voter is validated against the current voter set. If the voter does not exist,
2356+ * or if the request does not include a valid voter id or endpoint, the request will
2357+ * fail immediately.
2358+ *
2359+ * This API performs several checks before committing the removal:
2360+ * - Ensures the leader is not currently processing another voter change request.
2361+ * - Checks that the high watermark has been established and the current epoch is committed.
2362+ * - Validates that the cluster supports the required kraft.version for reconfiguration.
2363+ * - Confirms that there are no uncommitted voter changes pending in the log.
2364+ *
2365+ * When all checks pass, the voter is removed from the voter set and a new VotersRecord
2366+ * is appended to the log.
2367+ *
2368+ * This API may return the following errors:
2369+ *
2370+ * - {@link Errors#INCONSISTENT_CLUSTER_ID} if the cluster id is provided but does
2371+ * not match this cluster's id
2372+ * - {@link Errors#FENCED_LEADER_EPOCH} if the epoch is smaller than this node's epoch
2373+ * - {@link Errors#UNKNOWN_LEADER_EPOCH} if the epoch is larger than this node's epoch
2374+ * - {@link Errors#NOT_LEADER_OR_FOLLOWER} if the request was sent to a broker that
2375+ * is not the current quorum leader
2376+ * - {@link Errors#BROKER_NOT_AVAILABLE} if this node is currently shutting down
2377+ * - {@link Errors#REQUEST_TIMED_OUT} if the leader is still processing a previous
2378+ * voter change, or if the high watermark has not yet advanced
2379+ * - {@link Errors#VOTER_NOT_FOUND} if the specified voter does not exist in the current set
2380+ * - {@link Errors#UNSUPPORTED_VERSION} if the cluster does not support the required kraft.version
2381+ * - {@link Errors#INVALID_REQUEST} if the request does not include a valid voter or endpoint
2382+ */
23132383 private CompletableFuture <RemoveRaftVoterResponseData > handleRemoveVoterRequest (
23142384 RaftRequest .Inbound requestMetadata ,
23152385 long currentTimeMs
0 commit comments