use of org.springframework.integration.leader.DefaultCandidate in project spring-integration by spring-projects.
the class RedisLockRegistryLeaderInitiatorTests method testDistributedLeaderElection.
@Test
@RedisAvailable
public void testDistributedLeaderElection() throws Exception {
CountDownLatch granted = new CountDownLatch(1);
CountingPublisher countingPublisher = new CountingPublisher(granted);
List<LockRegistryLeaderInitiator> initiators = new ArrayList<>();
for (int i = 0; i < 2; i++) {
RedisLockRegistry registry = new RedisLockRegistry(getConnectionFactoryForTest(), "LeaderInitiator");
LockRegistryLeaderInitiator initiator = new LockRegistryLeaderInitiator(registry, new DefaultCandidate("foo", "bar"));
initiator.setLeaderEventPublisher(countingPublisher);
initiators.add(initiator);
}
for (LockRegistryLeaderInitiator initiator : initiators) {
initiator.start();
}
assertThat(granted.await(10, TimeUnit.SECONDS), is(true));
LockRegistryLeaderInitiator initiator1 = countingPublisher.initiator;
LockRegistryLeaderInitiator initiator2 = null;
for (LockRegistryLeaderInitiator initiator : initiators) {
if (initiator != initiator1) {
initiator2 = initiator;
break;
}
}
assertNotNull(initiator2);
assertThat(initiator1.getContext().isLeader(), is(true));
assertThat(initiator2.getContext().isLeader(), is(false));
final CountDownLatch granted1 = new CountDownLatch(1);
final CountDownLatch granted2 = new CountDownLatch(1);
CountDownLatch revoked1 = new CountDownLatch(1);
CountDownLatch revoked2 = new CountDownLatch(1);
CountDownLatch acquireLockFailed1 = new CountDownLatch(1);
CountDownLatch acquireLockFailed2 = new CountDownLatch(1);
initiator1.setLeaderEventPublisher(new CountingPublisher(granted1, revoked1, acquireLockFailed1) {
@Override
public void publishOnRevoked(Object source, Context context, String role) {
try {
// It's difficult to see round-robin election, so block one initiator until the second is elected.
assertThat(granted2.await(10, TimeUnit.SECONDS), is(true));
} catch (InterruptedException e) {
// No op
}
super.publishOnRevoked(source, context, role);
}
});
initiator2.setLeaderEventPublisher(new CountingPublisher(granted2, revoked2, acquireLockFailed2) {
@Override
public void publishOnRevoked(Object source, Context context, String role) {
try {
// It's difficult to see round-robin election, so block one initiator until the second is elected.
assertThat(granted1.await(10, TimeUnit.SECONDS), is(true));
} catch (InterruptedException e) {
// No op
}
super.publishOnRevoked(source, context, role);
}
});
initiator1.getContext().yield();
assertThat(revoked1.await(10, TimeUnit.SECONDS), is(true));
assertThat(initiator2.getContext().isLeader(), is(true));
assertThat(initiator1.getContext().isLeader(), is(false));
initiator2.getContext().yield();
assertThat(revoked2.await(10, TimeUnit.SECONDS), is(true));
assertThat(initiator1.getContext().isLeader(), is(true));
assertThat(initiator2.getContext().isLeader(), is(false));
initiator2.stop();
CountDownLatch revoked11 = new CountDownLatch(1);
initiator1.setLeaderEventPublisher(new CountingPublisher(new CountDownLatch(1), revoked11, new CountDownLatch(1)));
initiator1.getContext().yield();
assertThat(revoked11.await(10, TimeUnit.SECONDS), is(true));
assertThat(initiator1.getContext().isLeader(), is(false));
initiator1.stop();
}
use of org.springframework.integration.leader.DefaultCandidate in project spring-integration by spring-projects.
the class LockRegistryLeaderInitiatorTests method competingWithErrorPublish.
@Test
public void competingWithErrorPublish() throws Exception {
LockRegistryLeaderInitiator another = new LockRegistryLeaderInitiator(this.registry, new DefaultCandidate());
CountDownLatch other = new CountDownLatch(1);
CountDownLatch failedAcquireLatch = new CountDownLatch(1);
another.setLeaderEventPublisher(new CountingPublisher(other, new CountDownLatch(1), failedAcquireLatch));
another.setPublishFailedEvents(true);
this.initiator.start();
assertThat(this.granted.await(20, TimeUnit.SECONDS), is(true));
another.start();
assertThat(failedAcquireLatch.await(20, TimeUnit.SECONDS), is(true));
this.initiator.stop();
assertThat(other.await(20, TimeUnit.SECONDS), is(true));
assertThat(another.getContext().isLeader(), is(true));
another.stop();
}
use of org.springframework.integration.leader.DefaultCandidate in project spring-integration by spring-projects.
the class LockRegistryLeaderInitiatorTests method competing.
@Test
public void competing() throws Exception {
LockRegistryLeaderInitiator another = new LockRegistryLeaderInitiator(this.registry, new DefaultCandidate());
CountDownLatch other = new CountDownLatch(1);
another.setLeaderEventPublisher(new CountingPublisher(other));
this.initiator.start();
assertThat(this.granted.await(20, TimeUnit.SECONDS), is(true));
another.start();
this.initiator.stop();
assertThat(other.await(20, TimeUnit.SECONDS), is(true));
assertThat(another.getContext().isLeader(), is(true));
another.stop();
}
use of org.springframework.integration.leader.DefaultCandidate in project spring-integration by spring-projects.
the class ZookeeperLeaderTests method testLeader.
@Test
public void testLeader() throws Exception {
assertFalse(this.adapter.isRunning());
LeaderEventPublisher publisher = publisher();
DefaultCandidate candidate1 = new DefaultCandidate("foo", "sitest");
LeaderInitiator initiator1 = new LeaderInitiator(this.client, candidate1, "/sitest");
initiator1.setLeaderEventPublisher(publisher);
initiator1.start();
DefaultCandidate candidate2 = new DefaultCandidate("bar", "sitest");
LeaderInitiator initiator2 = new LeaderInitiator(this.client, candidate2, "/sitest");
initiator2.setLeaderEventPublisher(publisher);
initiator2.start();
AbstractLeaderEvent event = this.events.poll(30, TimeUnit.SECONDS);
assertNotNull(event);
assertThat(event, instanceOf(OnGrantedEvent.class));
assertTrue(this.adapter.isRunning());
event.getContext().yield();
event = this.events.poll(30, TimeUnit.SECONDS);
assertNotNull(event);
assertThat(event, instanceOf(OnRevokedEvent.class));
assertFalse(this.adapter.isRunning());
this.yieldBarrier.countDown();
event = this.events.poll(30, TimeUnit.SECONDS);
assertNotNull(event);
assertThat(event, instanceOf(OnGrantedEvent.class));
assertTrue(this.adapter.isRunning());
initiator1.stop();
initiator2.stop();
event = this.events.poll(30, TimeUnit.SECONDS);
assertNotNull(event);
assertThat(event, instanceOf(OnRevokedEvent.class));
assertFalse(this.adapter.isRunning());
}
use of org.springframework.integration.leader.DefaultCandidate in project spring-integration by spring-projects.
the class LockRegistryLeaderInitiatorTests method competingWithLock.
@Test
public void competingWithLock() throws Exception {
// switch used to toggle which registry obtains lock
AtomicBoolean firstLocked = new AtomicBoolean(true);
// set up first registry instance - this one will be able to obtain lock initially
LockRegistry firstRegistry = mock(LockRegistry.class);
Lock firstLock = mock(Lock.class);
given(firstRegistry.obtain(anyString())).willReturn(firstLock);
given(firstLock.tryLock(anyLong(), any(TimeUnit.class))).willAnswer(i -> firstLocked.get());
// set up first initiator instance using first LockRegistry
LockRegistryLeaderInitiator first = new LockRegistryLeaderInitiator(firstRegistry, new DefaultCandidate());
CountDownLatch firstGranted = new CountDownLatch(1);
CountDownLatch firstRevoked = new CountDownLatch(1);
CountDownLatch firstAquireLockFailed = new CountDownLatch(1);
first.setHeartBeatMillis(10);
first.setBusyWaitMillis(1);
first.setLeaderEventPublisher(new CountingPublisher(firstGranted, firstRevoked, firstAquireLockFailed));
// set up second registry instance - this one will NOT be able to obtain lock initially
LockRegistry secondRegistry = mock(LockRegistry.class);
Lock secondLock = mock(Lock.class);
given(secondRegistry.obtain(anyString())).willReturn(secondLock);
given(secondLock.tryLock(anyLong(), any(TimeUnit.class))).willAnswer(i -> !firstLocked.get());
// set up second initiator instance using second LockRegistry
LockRegistryLeaderInitiator second = new LockRegistryLeaderInitiator(secondRegistry, new DefaultCandidate());
CountDownLatch secondGranted = new CountDownLatch(1);
CountDownLatch secondRevoked = new CountDownLatch(1);
CountDownLatch secondAquireLockFailed = new CountDownLatch(1);
second.setHeartBeatMillis(10);
second.setBusyWaitMillis(1);
second.setLeaderEventPublisher(new CountingPublisher(secondGranted, secondRevoked, secondAquireLockFailed));
// start initiators
first.start();
second.start();
// first initiator should lead and publish granted event
assertThat(firstGranted.await(10, TimeUnit.SECONDS), is(true));
assertThat(first.getContext().isLeader(), is(true));
assertThat(second.getContext().isLeader(), is(false));
// simulate first registry instance unable to obtain lock, for example due to lock timeout
firstLocked.set(false);
// second initiator should take lead and publish granted event, first initiator should publish revoked event
assertThat(secondGranted.await(10, TimeUnit.SECONDS), is(true));
assertThat(firstRevoked.await(10, TimeUnit.SECONDS), is(true));
assertThat(second.getContext().isLeader(), is(true));
assertThat(first.getContext().isLeader(), is(false));
first.stop();
second.stop();
}
Aggregations