From e6d0a4f826164e0da6c440afb63533dab15e0abd Mon Sep 17 00:00:00 2001 From: Ivan Zaitsev Date: Tue, 7 Feb 2023 17:36:29 +0200 Subject: [PATCH] GH-4008: ZK: Add leader and participants support Fixes https://github.com/spring-projects/spring-integration/issues/4008 Impossible to retrieve current leader id from ZK `LeaderInitiator` * change return type of `LeaderInitiator.getContext()` from `Context` to `CuratorContext` * add `getLeader()` method to `CuratorContext` * add `getParticipants()` method to `CuratorContext` --- .../zookeeper/leader/LeaderInitiator.java | 67 ++++++++++++++----- .../LeaderInitiatorFactoryBeanTests.java | 6 ++ 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/leader/LeaderInitiator.java b/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/leader/LeaderInitiator.java index d8f7ba6f95..9db5c2abc2 100644 --- a/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/leader/LeaderInitiator.java +++ b/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/leader/LeaderInitiator.java @@ -16,12 +16,16 @@ package org.springframework.integration.zookeeper.leader; +import java.util.Collection; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.imps.CuratorFrameworkState; import org.apache.curator.framework.recipes.leader.LeaderSelector; import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter; +import org.apache.curator.framework.recipes.leader.Participant; import org.springframework.context.SmartLifecycle; import org.springframework.integration.leader.Candidate; @@ -38,6 +42,7 @@ import org.springframework.util.StringUtils; * @author Janne Valkealahti * @author Gary Russell * @author Artem Bilan + * @author Ivan Zaitsev * * @since 4.2 */ @@ -49,6 +54,8 @@ public class LeaderInitiator implements SmartLifecycle { private final CuratorContext context = new CuratorContext(); + private final CuratorContext nullContext = new NullCuratorContext(); + /** * Curator client. */ @@ -59,20 +66,6 @@ public class LeaderInitiator implements SmartLifecycle { */ private final Candidate candidate; - private final Context nullContext = new Context() { - - @Override - public boolean isLeader() { - return false; - } - - @Override - public String getRole() { - return LeaderInitiator.this.candidate.getRole(); - } - - }; - private final Object lifecycleMonitor = new Object(); /** @@ -214,7 +207,7 @@ public class LeaderInitiator implements SmartLifecycle { * @return the context. * @since 5.0 */ - public Context getContext() { + public CuratorContext getContext() { if (this.leaderSelector == null) { return this.nullContext; } @@ -283,7 +276,7 @@ public class LeaderInitiator implements SmartLifecycle { /** * Implementation of leadership context backed by Curator. */ - private class CuratorContext implements Context { + public class CuratorContext implements Context { CuratorContext() { } @@ -303,6 +296,24 @@ public class LeaderInitiator implements SmartLifecycle { return LeaderInitiator.this.candidate.getRole(); } + /** + * Get the leader + * @return the leader. + * @since 6.0.3 + */ + public Participant getLeader() throws Exception { + return LeaderInitiator.this.leaderSelector.getLeader(); + } + + /** + * Get the list of participants + * @return list of participants. + * @since 6.0.3 + */ + public Collection getParticipants() throws Exception { + return LeaderInitiator.this.leaderSelector.getParticipants(); + } + @Override public String toString() { return "CuratorContext{role=" + LeaderInitiator.this.candidate.getRole() + @@ -312,4 +323,28 @@ public class LeaderInitiator implements SmartLifecycle { } + private class NullCuratorContext extends CuratorContext { + + @Override + public boolean isLeader() { + return false; + } + + @Override + public String getRole() { + return LeaderInitiator.this.candidate.getRole(); + } + + @Override + public Participant getLeader() throws Exception { + return null; + } + + @Override + public Collection getParticipants() throws Exception { + return List.of(); + } + + } + } diff --git a/spring-integration-zookeeper/src/test/java/org/springframework/integration/zookeeper/config/LeaderInitiatorFactoryBeanTests.java b/spring-integration-zookeeper/src/test/java/org/springframework/integration/zookeeper/config/LeaderInitiatorFactoryBeanTests.java index fb1e43611d..7ba70d8dee 100644 --- a/spring-integration-zookeeper/src/test/java/org/springframework/integration/zookeeper/config/LeaderInitiatorFactoryBeanTests.java +++ b/spring-integration-zookeeper/src/test/java/org/springframework/integration/zookeeper/config/LeaderInitiatorFactoryBeanTests.java @@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.recipes.leader.Participant; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -47,6 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Gary Russell * @author Artem Bilan + * @author Ivan Zaitsev * * @since 4.2 * @@ -88,6 +90,8 @@ public class LeaderInitiatorFactoryBeanTests extends ZookeeperTestSupport { public void testExceptionFromEvent() throws Exception { CountDownLatch onGranted = new CountDownLatch(1); + Participant participant = new Participant("foo", true); + LeaderInitiator initiator = new LeaderInitiator(client, new DefaultCandidate("foo", "bar")); initiator.setLeaderEventPublisher(new DefaultLeaderEventPublisher() { @@ -110,6 +114,8 @@ public class LeaderInitiatorFactoryBeanTests extends ZookeeperTestSupport { assertThat(onGranted.await(10, TimeUnit.SECONDS)).isTrue(); assertThat(initiator.getContext().isLeader()).isTrue(); assertThat(initiator.getContext().getRole()).isEqualTo("bar"); + assertThat(initiator.getContext().getLeader()).isEqualTo(participant); + assertThat(initiator.getContext().getParticipants()).contains(participant); initiator.stop(); }