use of org.neo4j.cluster.member.ClusterMemberEvents in project neo4j by neo4j.
the class HighAvailabilityMemberStateMachineTest method whenInSlaveStateLosingOtherSlaveShouldNotPutInPending.
@Test
public void whenInSlaveStateLosingOtherSlaveShouldNotPutInPending() throws Throwable {
// Given
InstanceId me = new InstanceId(1);
InstanceId master = new InstanceId(2);
InstanceId otherSlave = new InstanceId(3);
HighAvailabilityMemberContext context = new SimpleHighAvailabilityMemberContext(me, false);
AvailabilityGuard guard = mock(AvailabilityGuard.class);
ObservedClusterMembers members = mockClusterMembers(me, singletonList(master), singletonList(otherSlave));
ClusterMemberEvents events = mock(ClusterMemberEvents.class);
ClusterMemberListenerContainer memberListenerContainer = mockAddClusterMemberListener(events);
HighAvailabilityMemberStateMachine stateMachine = buildMockedStateMachine(context, events, members, guard);
stateMachine.init();
ClusterMemberListener memberListener = memberListenerContainer.get();
HAStateChangeListener probe = new HAStateChangeListener();
stateMachine.addHighAvailabilityMemberListener(probe);
// Send it to MASTER
memberListener.memberIsAvailable(MASTER, master, URI.create("ha://whatever"), StoreId.DEFAULT);
memberListener.memberIsAvailable(SLAVE, me, URI.create("ha://whatever3"), StoreId.DEFAULT);
memberListener.memberIsAvailable(SLAVE, otherSlave, URI.create("ha://whatever2"), StoreId.DEFAULT);
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.SLAVE));
// When
memberListener.memberIsFailed(otherSlave);
// Then
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.SLAVE));
assertThat(probe.instanceStops, is(false));
}
use of org.neo4j.cluster.member.ClusterMemberEvents in project neo4j by neo4j.
the class HighAvailabilityMemberStateMachineTest method whenInMasterStateLosingQuorumFromTwoInstancesShouldRemainMaster.
@Test
public void whenInMasterStateLosingQuorumFromTwoInstancesShouldRemainMaster() throws Throwable {
// Given
InstanceId me = new InstanceId(1);
InstanceId other = new InstanceId(2);
HighAvailabilityMemberContext context = new SimpleHighAvailabilityMemberContext(me, false);
AvailabilityGuard guard = mock(AvailabilityGuard.class);
ObservedClusterMembers members = mockClusterMembers(me, emptyList(), singletonList(other));
ClusterMemberEvents events = mock(ClusterMemberEvents.class);
ClusterMemberListenerContainer memberListenerContainer = mockAddClusterMemberListener(events);
HighAvailabilityMemberStateMachine stateMachine = buildMockedStateMachine(context, events, members, guard);
stateMachine.init();
ClusterMemberListener memberListener = memberListenerContainer.get();
HAStateChangeListener probe = new HAStateChangeListener();
stateMachine.addHighAvailabilityMemberListener(probe);
// Send it to MASTER
memberListener.coordinatorIsElected(me);
memberListener.memberIsAvailable(MASTER, me, URI.create("ha://whatever"), StoreId.DEFAULT);
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.MASTER));
// When
memberListener.memberIsFailed(new InstanceId(2));
// Then
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.MASTER));
assertThat(probe.instanceStops, is(false));
assertThat(probe.instanceDetached, is(false));
}
use of org.neo4j.cluster.member.ClusterMemberEvents in project neo4j by neo4j.
the class ClusterTopologyChangesIT method slaveShouldServeTxsAfterMasterLostQuorumWentToPendingAndThenQuorumWasRestored.
@Test
@Ignore
public void slaveShouldServeTxsAfterMasterLostQuorumWentToPendingAndThenQuorumWasRestored() throws Throwable {
// GIVEN: cluster with 3 members
HighlyAvailableGraphDatabase master = cluster.getMaster();
final HighlyAvailableGraphDatabase slave1 = cluster.getAnySlave();
final HighlyAvailableGraphDatabase slave2 = cluster.getAnySlave(slave1);
final CountDownLatch slave1Left = new CountDownLatch(1);
final CountDownLatch slave2Left = new CountDownLatch(1);
clusterClientOf(master).addHeartbeatListener(new HeartbeatListener.Adapter() {
@Override
public void failed(InstanceId server) {
if (instanceIdOf(slave1).equals(server)) {
slave1Left.countDown();
} else if (instanceIdOf(slave2).equals(server)) {
slave2Left.countDown();
}
}
});
// fail slave1 and await master to spot the failure
RepairKit slave1RepairKit = cluster.fail(slave1);
assertTrue(slave1Left.await(60, SECONDS));
// fail slave2 and await master to spot the failure
RepairKit slave2RepairKit = cluster.fail(slave2);
assertTrue(slave2Left.await(60, SECONDS));
// master loses quorum and goes to PENDING, cluster is unavailable
cluster.await(masterAvailable().negate());
assertEquals(HighAvailabilityMemberState.PENDING, master.getInstanceState());
// WHEN: both slaves are repaired, majority restored, quorum can be achieved
slave1RepairKit.repair();
slave2RepairKit.repair();
// whole cluster looks fine, but slaves have stale value of the epoch if they rejoin the cluster in SLAVE state
cluster.await(masterAvailable());
cluster.await(masterSeesSlavesAsAvailable(2));
HighlyAvailableGraphDatabase newMaster = cluster.getMaster();
final HighlyAvailableGraphDatabase newSlave1 = cluster.getAnySlave();
final HighlyAvailableGraphDatabase newSlave2 = cluster.getAnySlave(newSlave1);
// now adding another failing listener and wait for the failure due to stale epoch
final CountDownLatch slave1Unavailable = new CountDownLatch(1);
final CountDownLatch slave2Unavailable = new CountDownLatch(1);
ClusterMemberEvents clusterEvents = newMaster.getDependencyResolver().resolveDependency(ClusterMemberEvents.class);
clusterEvents.addClusterMemberListener(new ClusterMemberListener.Adapter() {
@Override
public void memberIsUnavailable(String role, InstanceId unavailableId) {
if (instanceIdOf(newSlave1).equals(unavailableId)) {
slave1Unavailable.countDown();
} else if (instanceIdOf(newSlave2).equals(unavailableId)) {
slave2Unavailable.countDown();
}
}
});
// attempt to perform transactions on both slaves throws, election is triggered
attemptTransactions(newSlave1, newSlave2);
// set a timeout in case the instance does not have stale epoch
assertTrue(slave1Unavailable.await(60, TimeUnit.SECONDS));
assertTrue(slave2Unavailable.await(60, TimeUnit.SECONDS));
// THEN: done with election, cluster feels good and able to serve transactions
cluster.info("Waiting for cluster to stabilize");
cluster.await(allSeesAllAsAvailable());
cluster.info("Assert ok");
assertNotNull(createNodeOn(newMaster));
assertNotNull(createNodeOn(newSlave1));
assertNotNull(createNodeOn(newSlave2));
}
use of org.neo4j.cluster.member.ClusterMemberEvents in project neo4j by neo4j.
the class HighAvailabilityMemberStateMachineTest method whenInSlaveStateWith2MemberClusterLosingMasterShouldPutInPending.
@Test
public void whenInSlaveStateWith2MemberClusterLosingMasterShouldPutInPending() throws Throwable {
// Given
InstanceId me = new InstanceId(1);
InstanceId master = new InstanceId(2);
HighAvailabilityMemberContext context = new SimpleHighAvailabilityMemberContext(me, false);
AvailabilityGuard guard = mock(AvailabilityGuard.class);
ObservedClusterMembers members = mockClusterMembers(me, emptyList(), singletonList(master));
ClusterMemberEvents events = mock(ClusterMemberEvents.class);
ClusterMemberListenerContainer memberListenerContainer = mockAddClusterMemberListener(events);
HighAvailabilityMemberStateMachine stateMachine = buildMockedStateMachine(context, events, members, guard);
stateMachine.init();
ClusterMemberListener memberListener = memberListenerContainer.get();
HAStateChangeListener probe = new HAStateChangeListener();
stateMachine.addHighAvailabilityMemberListener(probe);
// Send it to MASTER
memberListener.coordinatorIsElected(master);
memberListener.memberIsAvailable(MASTER, master, URI.create("ha://whatever"), StoreId.DEFAULT);
memberListener.memberIsAvailable(SLAVE, me, URI.create("ha://whatever3"), StoreId.DEFAULT);
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.SLAVE));
// When
memberListener.memberIsFailed(master);
// Then
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.PENDING));
assertThat(probe.instanceStops, is(false));
assertThat(probe.instanceDetached, is(true));
verify(guard, times(1)).require(any(AvailabilityRequirement.class));
}
use of org.neo4j.cluster.member.ClusterMemberEvents in project neo4j by neo4j.
the class HighAvailabilityMemberStateMachineTest method whenSlaveOnlyIsElectedStayInPending.
@Test
public void whenSlaveOnlyIsElectedStayInPending() throws Throwable {
// Given
InstanceId me = new InstanceId(1);
HighAvailabilityMemberContext context = new SimpleHighAvailabilityMemberContext(me, true);
ClusterMemberEvents events = mock(ClusterMemberEvents.class);
ClusterMemberListenerContainer memberListenerContainer = mockAddClusterMemberListener(events);
HighAvailabilityMemberStateMachine stateMachine = buildMockedStateMachine(context, events);
stateMachine.init();
ClusterMemberListener memberListener = memberListenerContainer.get();
// When
memberListener.coordinatorIsElected(me);
// Then
assertThat(stateMachine.getCurrentState(), equalTo(HighAvailabilityMemberState.PENDING));
}
Aggregations