Search in sources :

Example 1 with FollowerCheckRequest

use of org.opensearch.cluster.coordination.FollowersChecker.FollowerCheckRequest in project OpenSearch by opensearch-project.

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(), TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> follower, null, emptySet());
    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;
    }, () -> new StatusInfo(HEALTHY, "healthy-info"));
    {
        // 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 OpenSearchException(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.opensearch.cluster.node.DiscoveryNode) TransportRequest(org.opensearch.transport.TransportRequest) TransportResponseHandler(org.opensearch.transport.TransportResponseHandler) AtomicReference(java.util.concurrent.atomic.AtomicReference) FollowerCheckRequest(org.opensearch.cluster.coordination.FollowersChecker.FollowerCheckRequest) TransportResponse(org.opensearch.transport.TransportResponse) ConnectTransportException(org.opensearch.transport.ConnectTransportException) TransportException(org.opensearch.transport.TransportException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Empty(org.opensearch.transport.TransportResponse.Empty) TransportService(org.opensearch.transport.TransportService) StatusInfo(org.opensearch.monitor.StatusInfo) MockTransport(org.opensearch.test.transport.MockTransport) StreamInput(org.opensearch.common.io.stream.StreamInput) OpenSearchException(org.opensearch.OpenSearchException) Settings(org.opensearch.common.settings.Settings)

Example 2 with FollowerCheckRequest

use of org.opensearch.cluster.coordination.FollowersChecker.FollowerCheckRequest in project OpenSearch by opensearch-project.

the class FollowersCheckerTests method testUnhealthyNodeRejectsImmediately.

public void testUnhealthyNodeRejectsImmediately() {
    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(), TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> follower, null, emptySet());
    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;
    }, () -> new StatusInfo(UNHEALTHY, "unhealthy-info"));
    final long leaderTerm = randomLongBetween(2, Long.MAX_VALUE);
    final long followerTerm = randomLongBetween(1, leaderTerm - 1);
    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()));
}
Also used : DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) TransportRequest(org.opensearch.transport.TransportRequest) Empty(org.opensearch.transport.TransportResponse.Empty) AtomicReference(java.util.concurrent.atomic.AtomicReference) FollowerCheckRequest(org.opensearch.cluster.coordination.FollowersChecker.FollowerCheckRequest) ConnectTransportException(org.opensearch.transport.ConnectTransportException) TransportException(org.opensearch.transport.TransportException) TransportResponse(org.opensearch.transport.TransportResponse) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Empty(org.opensearch.transport.TransportResponse.Empty) TransportService(org.opensearch.transport.TransportService) StatusInfo(org.opensearch.monitor.StatusInfo) MockTransport(org.opensearch.test.transport.MockTransport) StreamInput(org.opensearch.common.io.stream.StreamInput) Settings(org.opensearch.common.settings.Settings)

Aggregations

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