use of org.opensearch.transport.TransportResponse.Empty in project OpenSearch by opensearch-project.
the class JoinHelper method sendJoinRequest.
public void sendJoinRequest(DiscoveryNode destination, long term, Optional<Join> optionalJoin, Runnable onCompletion) {
assert destination.isMasterNode() : "trying to join master-ineligible " + destination;
final StatusInfo statusInfo = nodeHealthService.getHealth();
if (statusInfo.getStatus() == UNHEALTHY) {
logger.debug("dropping join request to [{}]: [{}]", destination, statusInfo.getInfo());
return;
}
final JoinRequest joinRequest = new JoinRequest(transportService.getLocalNode(), term, optionalJoin);
final Tuple<DiscoveryNode, JoinRequest> dedupKey = Tuple.tuple(destination, joinRequest);
if (pendingOutgoingJoins.add(dedupKey)) {
logger.debug("attempting to join {} with {}", destination, joinRequest);
transportService.sendRequest(destination, JOIN_ACTION_NAME, joinRequest, TransportRequestOptions.EMPTY, new TransportResponseHandler<Empty>() {
@Override
public Empty read(StreamInput in) {
return Empty.INSTANCE;
}
@Override
public void handleResponse(Empty response) {
pendingOutgoingJoins.remove(dedupKey);
logger.debug("successfully joined {} with {}", destination, joinRequest);
lastFailedJoinAttempt.set(null);
onCompletion.run();
}
@Override
public void handleException(TransportException exp) {
pendingOutgoingJoins.remove(dedupKey);
logger.info(() -> new ParameterizedMessage("failed to join {} with {}", destination, joinRequest), exp);
FailedJoinAttempt attempt = new FailedJoinAttempt(destination, joinRequest, exp);
attempt.logNow();
lastFailedJoinAttempt.set(attempt);
onCompletion.run();
}
@Override
public String executor() {
return Names.SAME;
}
});
} else {
logger.debug("already attempting to join {} with request {}, not sending request", destination, joinRequest);
}
}
use of org.opensearch.transport.TransportResponse.Empty in project OpenSearch by opensearch-project.
the class FollowersCheckerTests method testFailureCounterResetsOnSuccess.
public void testFailureCounterResetsOnSuccess() {
final Settings settings = randomSettings();
final int retryCount = FOLLOWER_CHECK_RETRY_COUNT_SETTING.get(settings);
final int maxRecoveries = randomIntBetween(3, 10);
// passes just enough checks to keep it alive, up to maxRecoveries, and then fails completely
testBehaviourOfFailingNode(settings, new Supplier<Empty>() {
private int checkIndex;
private int recoveries;
@Override
public Empty get() {
checkIndex++;
if (checkIndex % retryCount == 0 && recoveries < maxRecoveries) {
recoveries++;
return Empty.INSTANCE;
}
throw new OpenSearchException("simulated exception");
}
}, "followers check retry count exceeded", (FOLLOWER_CHECK_RETRY_COUNT_SETTING.get(settings) * (maxRecoveries + 1) - 1) * FOLLOWER_CHECK_INTERVAL_SETTING.get(settings).millis(), () -> new StatusInfo(HEALTHY, "healthy-info"));
}
use of org.opensearch.transport.TransportResponse.Empty in project OpenSearch by opensearch-project.
the class RestBuilderListenerTests method testXContentBuilderClosedInBuildResponse.
public void testXContentBuilderClosedInBuildResponse() throws Exception {
AtomicReference<XContentBuilder> builderAtomicReference = new AtomicReference<>();
RestBuilderListener<TransportResponse.Empty> builderListener = new RestBuilderListener<Empty>(new FakeRestChannel(new FakeRestRequest(), randomBoolean(), 1)) {
@Override
public RestResponse buildResponse(Empty empty, XContentBuilder builder) throws Exception {
builderAtomicReference.set(builder);
builder.close();
return new BytesRestResponse(RestStatus.OK, BytesRestResponse.TEXT_CONTENT_TYPE, BytesArray.EMPTY);
}
};
builderListener.buildResponse(Empty.INSTANCE);
assertNotNull(builderAtomicReference.get());
assertTrue(builderAtomicReference.get().generator().isClosed());
}
use of org.opensearch.transport.TransportResponse.Empty in project OpenSearch by opensearch-project.
the class RestBuilderListenerTests method testXContentBuilderNotClosedInBuildResponseAssertionsEnabled.
public void testXContentBuilderNotClosedInBuildResponseAssertionsEnabled() throws Exception {
assumeTrue("tests are not being run with assertions", RestBuilderListener.class.desiredAssertionStatus());
RestBuilderListener<TransportResponse.Empty> builderListener = new RestBuilderListener<Empty>(new FakeRestChannel(new FakeRestRequest(), randomBoolean(), 1)) {
@Override
public RestResponse buildResponse(Empty empty, XContentBuilder builder) throws Exception {
return new BytesRestResponse(RestStatus.OK, BytesRestResponse.TEXT_CONTENT_TYPE, BytesArray.EMPTY);
}
};
AssertionError error = expectThrows(AssertionError.class, () -> builderListener.buildResponse(Empty.INSTANCE));
assertEquals("callers should ensure the XContentBuilder is closed themselves", error.getMessage());
}
use of org.opensearch.transport.TransportResponse.Empty in project OpenSearch by opensearch-project.
the class FollowersCheckerTests method testBehaviourOfFailingNode.
private void testBehaviourOfFailingNode(Settings testSettings, Supplier<TransportResponse.Empty> responder, String failureReason, long expectedFailureTime, NodeHealthService nodeHealthService) {
final DiscoveryNode localNode = new DiscoveryNode("local-node", buildNewFakeTransportAddress(), Version.CURRENT);
final DiscoveryNode otherNode = new DiscoveryNode("other-node", buildNewFakeTransportAddress(), Version.CURRENT);
final Settings settings = Settings.builder().put(NODE_NAME_SETTING.getKey(), localNode.getName()).put(testSettings).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) {
assertNotEquals(node, localNode);
deterministicTaskQueue.scheduleNow(new Runnable() {
@Override
public void run() {
if (node.equals(otherNode) == false) {
// other nodes are ok
handleResponse(requestId, Empty.INSTANCE);
return;
}
try {
final Empty response = responder.get();
if (response != null) {
handleResponse(requestId, response);
}
} catch (Exception e) {
handleRemoteError(requestId, e);
}
}
@Override
public String toString() {
return "sending response to [" + action + "][" + requestId + "] from " + node;
}
});
}
};
final TransportService transportService = mockTransport.createTransportService(settings, deterministicTaskQueue.getThreadPool(), TransportService.NOOP_TRANSPORT_INTERCEPTOR, boundTransportAddress -> localNode, null, emptySet());
transportService.start();
transportService.acceptIncomingRequests();
final AtomicBoolean nodeFailed = new AtomicBoolean();
final FollowersChecker followersChecker = new FollowersChecker(settings, transportService, fcr -> {
assert false : fcr;
}, (node, reason) -> {
assertTrue(nodeFailed.compareAndSet(false, true));
assertThat(reason, equalTo(failureReason));
}, nodeHealthService);
DiscoveryNodes discoveryNodes = DiscoveryNodes.builder().add(localNode).add(otherNode).localNodeId(localNode.getId()).build();
followersChecker.setCurrentNodes(discoveryNodes);
while (nodeFailed.get() == false) {
if (deterministicTaskQueue.hasRunnableTasks() == false) {
deterministicTaskQueue.advanceTime();
}
deterministicTaskQueue.runAllRunnableTasks();
}
assertThat(deterministicTaskQueue.getCurrentTimeMillis(), equalTo(expectedFailureTime));
assertThat(followersChecker.getFaultyNodes(), contains(otherNode));
deterministicTaskQueue.runAllTasks();
// add another node and see that it schedules checks for this new node but keeps on considering the old one faulty
final DiscoveryNode otherNode2 = new DiscoveryNode("other-node-2", buildNewFakeTransportAddress(), Version.CURRENT);
discoveryNodes = DiscoveryNodes.builder(discoveryNodes).add(otherNode2).build();
followersChecker.setCurrentNodes(discoveryNodes);
deterministicTaskQueue.runAllRunnableTasks();
deterministicTaskQueue.advanceTime();
deterministicTaskQueue.runAllRunnableTasks();
assertThat(followersChecker.getFaultyNodes(), contains(otherNode));
// remove the faulty node and see that it is removed
discoveryNodes = DiscoveryNodes.builder(discoveryNodes).remove(otherNode).build();
followersChecker.setCurrentNodes(discoveryNodes);
assertThat(followersChecker.getFaultyNodes(), empty());
deterministicTaskQueue.runAllRunnableTasks();
deterministicTaskQueue.advanceTime();
deterministicTaskQueue.runAllRunnableTasks();
// remove the working node and see that everything eventually stops
discoveryNodes = DiscoveryNodes.builder(discoveryNodes).remove(otherNode2).build();
followersChecker.setCurrentNodes(discoveryNodes);
deterministicTaskQueue.runAllTasks();
// add back the faulty node afresh and see that it fails again
discoveryNodes = DiscoveryNodes.builder(discoveryNodes).add(otherNode).build();
followersChecker.setCurrentNodes(discoveryNodes);
nodeFailed.set(false);
assertThat(followersChecker.getFaultyNodes(), empty());
deterministicTaskQueue.runAllTasksInTimeOrder();
assertTrue(nodeFailed.get());
assertThat(followersChecker.getFaultyNodes(), contains(otherNode));
}
Aggregations