Search in sources :

Example 1 with DefaultCandidate

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();
}
Also used : Context(org.springframework.integration.leader.Context) ArrayList(java.util.ArrayList) DefaultCandidate(org.springframework.integration.leader.DefaultCandidate) CountDownLatch(java.util.concurrent.CountDownLatch) LockRegistryLeaderInitiator(org.springframework.integration.support.leader.LockRegistryLeaderInitiator) RedisLockRegistry(org.springframework.integration.redis.util.RedisLockRegistry) RedisAvailable(org.springframework.integration.redis.rules.RedisAvailable) Test(org.junit.Test)

Example 2 with DefaultCandidate

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();
}
Also used : DefaultCandidate(org.springframework.integration.leader.DefaultCandidate) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 3 with DefaultCandidate

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();
}
Also used : DefaultCandidate(org.springframework.integration.leader.DefaultCandidate) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 4 with DefaultCandidate

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());
}
Also used : AbstractLeaderEvent(org.springframework.integration.leader.event.AbstractLeaderEvent) LeaderInitiator(org.springframework.integration.zookeeper.leader.LeaderInitiator) OnGrantedEvent(org.springframework.integration.leader.event.OnGrantedEvent) LeaderEventPublisher(org.springframework.integration.leader.event.LeaderEventPublisher) DefaultLeaderEventPublisher(org.springframework.integration.leader.event.DefaultLeaderEventPublisher) DefaultCandidate(org.springframework.integration.leader.DefaultCandidate) OnRevokedEvent(org.springframework.integration.leader.event.OnRevokedEvent) Test(org.junit.Test)

Example 5 with DefaultCandidate

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();
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) LockRegistry(org.springframework.integration.support.locks.LockRegistry) DefaultLockRegistry(org.springframework.integration.support.locks.DefaultLockRegistry) DefaultCandidate(org.springframework.integration.leader.DefaultCandidate) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Lock(java.util.concurrent.locks.Lock) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)7 DefaultCandidate (org.springframework.integration.leader.DefaultCandidate)7 CountDownLatch (java.util.concurrent.CountDownLatch)6 Context (org.springframework.integration.leader.Context)3 ArrayList (java.util.ArrayList)2 DefaultLeaderEventPublisher (org.springframework.integration.leader.event.DefaultLeaderEventPublisher)2 LockRegistryLeaderInitiator (org.springframework.integration.support.leader.LockRegistryLeaderInitiator)2 LeaderInitiator (org.springframework.integration.zookeeper.leader.LeaderInitiator)2 TimeUnit (java.util.concurrent.TimeUnit)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Lock (java.util.concurrent.locks.Lock)1 ReentrantLock (java.util.concurrent.locks.ReentrantLock)1 DefaultLockRepository (org.springframework.integration.jdbc.lock.DefaultLockRepository)1 JdbcLockRegistry (org.springframework.integration.jdbc.lock.JdbcLockRegistry)1 AbstractLeaderEvent (org.springframework.integration.leader.event.AbstractLeaderEvent)1 LeaderEventPublisher (org.springframework.integration.leader.event.LeaderEventPublisher)1 OnGrantedEvent (org.springframework.integration.leader.event.OnGrantedEvent)1 OnRevokedEvent (org.springframework.integration.leader.event.OnRevokedEvent)1 RedisAvailable (org.springframework.integration.redis.rules.RedisAvailable)1 RedisLockRegistry (org.springframework.integration.redis.util.RedisLockRegistry)1