Cyrill commented on code in PR #7242: URL: https://github.com/apache/ignite-3/pull/7242#discussion_r2741249382
########## modules/raft/src/main/java/org/apache/ignite/internal/raft/client/LeaderAvailabilityState.java: ########## @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.raft.client; + +import java.util.concurrent.CompletableFuture; +import org.apache.ignite.internal.logger.IgniteLogger; +import org.apache.ignite.internal.logger.Loggers; +import org.apache.ignite.internal.network.InternalClusterNode; +import org.jetbrains.annotations.VisibleForTesting; + +/** + * State machine for tracking leader availability. + * + * <p>Manages transitions between two states: + * <ul> + * <li>{@link State#WAITING_FOR_LEADER} - No leader is currently known, operations must wait</li> + * <li>{@link State#LEADER_AVAILABLE} - A leader is known, operations can proceed</li> + * </ul> + * + * <p>State transitions: + * <pre> + * WAITING_FOR_LEADER --[onLeaderElected]--> LEADER_AVAILABLE + * LEADER_AVAILABLE --[onGroupUnavailable]--> WAITING_FOR_LEADER + * Any state --[stop]--> stopped (terminal state) + * </pre> + * + * <p>Thread-safe: all public methods are synchronized or use proper synchronization. + */ +@VisibleForTesting +class LeaderAvailabilityState { + /** The logger. */ + private static final IgniteLogger LOG = Loggers.forClass(LeaderAvailabilityState.class); + + /** Possible states of leader availability. */ + enum State { + /** No leader is known, waiting for leader election. */ + WAITING_FOR_LEADER, + /** A leader is available and operations can proceed. */ + LEADER_AVAILABLE + } + + /** Current state. Guarded by {@code this}. */ + private State currentState = State.WAITING_FOR_LEADER; + + /** Current leader term. Initialized to -1 to accept term 0 as the first valid term. Guarded by {@code this}. */ + private long currentTerm = -1; + + /** Future that waiters block on. Guarded by {@code this}. */ + private CompletableFuture<Long> waiters = new CompletableFuture<>(); + + /** Whether the state machine has been stopped. Guarded by {@code this}. */ + private boolean stopped = false; + + /** Exception used to fail futures after destruction. Guarded by {@code this}. */ + private Throwable stopException; + + /** + * Returns a future that completes when a leader becomes available. + * + * <p>If a leader is already available, returns an already-completed future with the current term. + * Otherwise, returns a future that will complete when {@link #onLeaderElected} is called. + * If the state machine has been destroyed, returns a failed future. + * + * @return Future that completes with the leader term when a leader is available. + */ + synchronized CompletableFuture<Long> awaitLeader() { + if (stopped) { + return CompletableFuture.failedFuture(stopException); + } + if (currentState == State.LEADER_AVAILABLE) { + return CompletableFuture.completedFuture(currentTerm); + } + return waiters; + } + + /** + * Handles leader election notification. + * + * <p>Transitions from {@link State#WAITING_FOR_LEADER} to {@link State#LEADER_AVAILABLE} + * if the new term is greater than the current term. Stale notifications (with term <= current) + * are ignored. Has no effect if the state machine has been stopped. + * + * @param leader The newly elected leader node. + * @param term The term of the new leader. + */ + void onLeaderElected(InternalClusterNode leader, long term) { + CompletableFuture<Long> futureToComplete = null; + + synchronized (this) { Review Comment: done -- 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]
