Search in sources :

Example 1 with FollowerCheckRequest

use of org.elasticsearch.cluster.coordination.FollowersChecker.FollowerCheckRequest in project crate by crate.

the class FollowersCheckerTests method testResponder.

public void testResponder() {
    final DiscoveryNode leader = new DiscoveryNode("leader", buildNewFakeTransportAddress(), Version.CURRENT);
    final DiscoveryNode follower = new DiscoveryNode("follower", buildNewFakeTransportAddress(), Version.CURRENT);
    final Settings settings = Settings.builder().put(NODE_NAME_SETTING.getKey(), follower.getName()).build();
    final DeterministicTaskQueue deterministicTaskQueue = new DeterministicTaskQueue(settings, random());
    final MockTransport mockTransport = new MockTransport() {

        @Override
        protected void onSendRequest(long requestId, String action, TransportRequest request, DiscoveryNode node) {
            throw new AssertionError("no requests expected");
        }
    };
    final TransportService transportService = mockTransport.createTransportService(settings, deterministicTaskQueue.getThreadPool(), boundTransportAddress -> follower, null);
    transportService.start();
    transportService.acceptIncomingRequests();
    final AtomicBoolean calledCoordinator = new AtomicBoolean();
    final AtomicReference<RuntimeException> coordinatorException = new AtomicReference<>();
    final FollowersChecker followersChecker = new FollowersChecker(settings, transportService, fcr -> {
        assertTrue(calledCoordinator.compareAndSet(false, true));
        final RuntimeException exception = coordinatorException.get();
        if (exception != null) {
            throw exception;
        }
    }, (node, reason) -> {
        assert false : node;
    });
    {
        // Does not call into the coordinator in the normal case
        final long term = randomNonNegativeLong();
        followersChecker.updateFastResponseState(term, Mode.FOLLOWER);
        final ExpectsSuccess expectsSuccess = new ExpectsSuccess();
        transportService.sendRequest(follower, FOLLOWER_CHECK_ACTION_NAME, new FollowerCheckRequest(term, leader), expectsSuccess);
        deterministicTaskQueue.runAllTasks();
        assertTrue(expectsSuccess.succeeded());
        assertFalse(calledCoordinator.get());
    }
    {
        // Does not call into the coordinator for a term that's too low, just rejects immediately
        final long leaderTerm = randomLongBetween(1, Long.MAX_VALUE - 1);
        final long followerTerm = randomLongBetween(leaderTerm + 1, Long.MAX_VALUE);
        followersChecker.updateFastResponseState(followerTerm, Mode.FOLLOWER);
        final AtomicReference<TransportException> receivedException = new AtomicReference<>();
        transportService.sendRequest(follower, FOLLOWER_CHECK_ACTION_NAME, new FollowerCheckRequest(leaderTerm, leader), new TransportResponseHandler<TransportResponse.Empty>() {

            @Override
            public TransportResponse.Empty read(StreamInput in) {
                return TransportResponse.Empty.INSTANCE;
            }

            @Override
            public void handleResponse(TransportResponse.Empty response) {
                fail("unexpected success");
            }

            @Override
            public void handleException(TransportException exp) {
                assertThat(exp, not(nullValue()));
                assertTrue(receivedException.compareAndSet(null, exp));
            }

            @Override
            public String executor() {
                return Names.SAME;
            }
        });
        deterministicTaskQueue.runAllTasks();
        assertFalse(calledCoordinator.get());
        assertThat(receivedException.get(), not(nullValue()));
    }
    {
        // Calls into the coordinator if the term needs bumping
        final long leaderTerm = randomLongBetween(2, Long.MAX_VALUE);
        final long followerTerm = randomLongBetween(1, leaderTerm - 1);
        followersChecker.updateFastResponseState(followerTerm, Mode.FOLLOWER);
        final ExpectsSuccess expectsSuccess = new ExpectsSuccess();
        transportService.sendRequest(follower, FOLLOWER_CHECK_ACTION_NAME, new FollowerCheckRequest(leaderTerm, leader), expectsSuccess);
        deterministicTaskQueue.runAllTasks();
        assertTrue(expectsSuccess.succeeded());
        assertTrue(calledCoordinator.get());
        calledCoordinator.set(false);
    }
    {
        // Calls into the coordinator if not a follower
        final long term = randomNonNegativeLong();
        followersChecker.updateFastResponseState(term, randomFrom(Mode.LEADER, Mode.CANDIDATE));
        final ExpectsSuccess expectsSuccess = new ExpectsSuccess();
        transportService.sendRequest(follower, FOLLOWER_CHECK_ACTION_NAME, new FollowerCheckRequest(term, leader), expectsSuccess);
        deterministicTaskQueue.runAllTasks();
        assertTrue(expectsSuccess.succeeded());
        assertTrue(calledCoordinator.get());
        calledCoordinator.set(false);
    }
    {
        // If it calls into the coordinator and the coordinator throws an exception then it's passed back to the caller
        final long term = randomNonNegativeLong();
        followersChecker.updateFastResponseState(term, randomFrom(Mode.LEADER, Mode.CANDIDATE));
        final String exceptionMessage = "test simulated exception " + randomNonNegativeLong();
        coordinatorException.set(new ElasticsearchException(exceptionMessage));
        final AtomicReference<TransportException> receivedException = new AtomicReference<>();
        transportService.sendRequest(follower, FOLLOWER_CHECK_ACTION_NAME, new FollowerCheckRequest(term, leader), new TransportResponseHandler<TransportResponse.Empty>() {

            @Override
            public TransportResponse.Empty read(StreamInput in) {
                return TransportResponse.Empty.INSTANCE;
            }

            @Override
            public void handleResponse(TransportResponse.Empty response) {
                fail("unexpected success");
            }

            @Override
            public void handleException(TransportException exp) {
                assertThat(exp, not(nullValue()));
                assertTrue(receivedException.compareAndSet(null, exp));
            }

            @Override
            public String executor() {
                return Names.SAME;
            }
        });
        deterministicTaskQueue.runAllTasks();
        assertTrue(calledCoordinator.get());
        assertThat(receivedException.get(), not(nullValue()));
        assertThat(receivedException.get().getRootCause().getMessage(), equalTo(exceptionMessage));
    }
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) TransportRequest(org.elasticsearch.transport.TransportRequest) TransportResponseHandler(org.elasticsearch.transport.TransportResponseHandler) AtomicReference(java.util.concurrent.atomic.AtomicReference) ElasticsearchException(org.elasticsearch.ElasticsearchException) FollowerCheckRequest(org.elasticsearch.cluster.coordination.FollowersChecker.FollowerCheckRequest) TransportResponse(org.elasticsearch.transport.TransportResponse) ConnectTransportException(org.elasticsearch.transport.ConnectTransportException) TransportException(org.elasticsearch.transport.TransportException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Empty(org.elasticsearch.transport.TransportResponse.Empty) TransportService(org.elasticsearch.transport.TransportService) MockTransport(org.elasticsearch.test.transport.MockTransport) StreamInput(org.elasticsearch.common.io.stream.StreamInput) Settings(org.elasticsearch.common.settings.Settings)

Aggregations

AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 ElasticsearchException (org.elasticsearch.ElasticsearchException)1 FollowerCheckRequest (org.elasticsearch.cluster.coordination.FollowersChecker.FollowerCheckRequest)1 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)1 StreamInput (org.elasticsearch.common.io.stream.StreamInput)1 Settings (org.elasticsearch.common.settings.Settings)1 MockTransport (org.elasticsearch.test.transport.MockTransport)1 ConnectTransportException (org.elasticsearch.transport.ConnectTransportException)1 TransportException (org.elasticsearch.transport.TransportException)1 TransportRequest (org.elasticsearch.transport.TransportRequest)1 TransportResponse (org.elasticsearch.transport.TransportResponse)1 Empty (org.elasticsearch.transport.TransportResponse.Empty)1 TransportResponseHandler (org.elasticsearch.transport.TransportResponseHandler)1 TransportService (org.elasticsearch.transport.TransportService)1