@@ -74,12 +74,15 @@ public class LeaderElection implements Closeable, SessionListenableProvider {
7474 private final SemaphoreObserver semaphoreObserver ;
7575
7676 private final CountDownLatch startingLatch = new CountDownLatch (1 );
77- private AtomicReference <State > state = new AtomicReference <>(State .INITIAL );
78- private AtomicReference <Future <Status >> initializingTask = new AtomicReference <>(null );
77+ private final AtomicReference <State > state = new AtomicReference <>(State .INITIAL );
78+ private final AtomicReference <Future <Status >> initializingTask = new AtomicReference <>(null );
7979 private Future <Void > electionTask = null ;
8080 private volatile boolean autoRequeue = false ;
8181 private volatile boolean isLeader = false ;
8282
83+ /**
84+ * Internal state
85+ */
8386 private enum State {
8487 INITIAL ,
8588 STARTING ,
@@ -91,10 +94,10 @@ private enum State {
9194 /**
9295 * Creates a new LeaderElection instance with default settings.
9396 *
94- * @param client the coordination client to use
95- * @param coordinationNodePath path to the coordination node
96- * @param electionName name of the election (must be unique per coordination node)
97- * @param data optional data to associate with the leader (visible to all participants)
97+ * @param client the coordination client to use
98+ * @param coordinationNodePath path to the coordination node
99+ * @param electionName name of the election (must be unique per coordination node)
100+ * @param data optional data to associate with the leader (visible to all participants)
98101 * @param leaderElectionListener callback for leadership events
99102 */
100103 public LeaderElection (
@@ -118,12 +121,12 @@ public LeaderElection(
118121 /**
119122 * Creates a new LeaderElection instance with custom settings.
120123 *
121- * @param client the coordination client to use
122- * @param coordinationNodePath path to the coordination node
123- * @param electionName name of the election (must be unique per coordination node)
124- * @param data optional data to associate with the leader (visible to all participants)
124+ * @param client the coordination client to use
125+ * @param coordinationNodePath path to the coordination node
126+ * @param electionName name of the election (must be unique per coordination node)
127+ * @param data optional data to associate with the leader (visible to all participants)
125128 * @param leaderElectionListener callback for leadership events
126- * @param settings configuration settings for the election process
129+ * @param settings configuration settings for the election process
127130 * @throws NullPointerException if any required parameter is null
128131 */
129132 public LeaderElection (
@@ -185,6 +188,8 @@ public void start() {
185188 "Leader election may be started only once"
186189 );
187190
191+ logger .debug ("Starting leader election '{}' initialization" , electionName );
192+
188193 CompletableFuture <Status > connectionTask = executeWithRetry (coordinationSession ::connect );
189194 CompletableFuture <Status > semaphoreCreateTask = executeWithRetry (
190195 () -> coordinationSession .createSemaphore (electionName , MAX_LEASE )
@@ -459,12 +464,16 @@ private synchronized boolean stopInternal(State terminationState) {
459464 } catch (Exception e ) {
460465 logger .warn ("Error closing semaphore observer for {}: {}" , electionName , e .getMessage ());
461466 }
462-
463467 try {
464468 blockingExecutor .shutdown ();
465469 } catch (Exception e ) {
466470 logger .warn ("Error shutting down executor for {}: {}" , electionName , e .getMessage ());
467471 }
472+ try {
473+ coordinationSession .close ();
474+ } catch (Exception e ) {
475+ logger .warn ("Error closing session for {}: {}" , electionName , e .getMessage ());
476+ }
468477 return true ;
469478 }
470479}
0 commit comments