Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -91,35 +91,32 @@ public void testFailed() throws Exception {
assertThat(telemetry.getSuccessCount(), equalTo(0L));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(0));

// One remote is skipped, one is not
// Errors from both remotes
telemetry = getTelemetryFromFailedQuery("from logs-*,c*:no_such_index | stats sum (v)");

assertThat(telemetry.getTotalCount(), equalTo(1L));
assertThat(telemetry.getSuccessCount(), equalTo(0L));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(1));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(0));
assertThat(telemetry.getRemotesPerSearchAvg(), equalTo(2.0));
assertThat(telemetry.getRemotesPerSearchMax(), equalTo(2L));
assertThat(telemetry.getSearchCountWithSkippedRemotes(), equalTo(1L));
assertThat(telemetry.getSearchCountWithSkippedRemotes(), equalTo(0L));
Map<String, Long> expectedFailure = Map.of(CCSUsageTelemetry.Result.NOT_FOUND.getName(), 1L);
assertThat(telemetry.getFailureReasons(), equalTo(expectedFailure));
// cluster-b should be skipped
assertThat(telemetry.getByRemoteCluster().get(REMOTE2).getCount(), equalTo(0L));
assertThat(telemetry.getByRemoteCluster().get(REMOTE2).getSkippedCount(), equalTo(1L));

// this is only for cluster-a so no skipped remotes
telemetry = getTelemetryFromFailedQuery("from logs-*,cluster-a:no_such_index | stats sum (v)");
assertThat(telemetry.getTotalCount(), equalTo(2L));
assertThat(telemetry.getSuccessCount(), equalTo(0L));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(1));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(0));
assertThat(telemetry.getRemotesPerSearchAvg(), equalTo(2.0));
assertThat(telemetry.getRemotesPerSearchMax(), equalTo(2L));
assertThat(telemetry.getSearchCountWithSkippedRemotes(), equalTo(1L));
assertThat(telemetry.getSearchCountWithSkippedRemotes(), equalTo(0L));
expectedFailure = Map.of(CCSUsageTelemetry.Result.NOT_FOUND.getName(), 2L);
assertThat(telemetry.getFailureReasons(), equalTo(expectedFailure));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(1));
assertThat(telemetry.getByRemoteCluster().size(), equalTo(0));
}

// TODO: enable when skip-up patch is merged
// TODO: enable when skip-un patch is merged
// public void testSkipAllRemotes() throws Exception {
// var telemetry = getTelemetryFromQuery("from logs-*,c*:no_such_index | stats sum (v)", "unknown");
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,13 @@ static void updateExecutionInfoWithClustersWithNoMatchingIndices(EsqlExecutionIn

/**
* Rules enforced at planning time around non-matching indices
* P1. fail query if no matching indices on any cluster (VerificationException) - that is handled elsewhere (TODO: document where)
* P2. fail query if a skip_unavailable:false cluster has no matching indices (the local cluster already has this rule
* enforced at planning time)
* P3. fail query if the local cluster has no matching indices and a concrete index was specified
* 1. fail query if no matching indices on any cluster (VerificationException) - that is handled elsewhere
* 2. fail query if a cluster has no matching indices *and* a concrete index was specified - handled here
*/
String fatalErrorMessage = null;
/*
* These are clusters in the original request that are not present in the field-caps response. They were
* specified with an index expression matched no indices, so the search on that cluster is done.
* specified with an index expression that matched no indices, so the search on that cluster is done.
* Mark it as SKIPPED with 0 shards searched and took=0.
*/
for (String c : clustersWithNoMatchingIndices) {
Expand All @@ -216,7 +214,7 @@ static void updateExecutionInfoWithClustersWithNoMatchingIndices(EsqlExecutionIn
continue;
}
final String indexExpression = executionInfo.getCluster(c).getIndexExpression();
if (missingIndicesIsFatal(c, executionInfo)) {
if (concreteIndexRequested(executionInfo.getCluster(c).getIndexExpression())) {
String error = Strings.format(
"Unknown index [%s]",
(c.equals(RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY) ? indexExpression : c + ":" + indexExpression)
Expand All @@ -227,10 +225,11 @@ static void updateExecutionInfoWithClustersWithNoMatchingIndices(EsqlExecutionIn
fatalErrorMessage += "; " + error;
}
} else {
// handles local cluster (when no concrete indices requested) and skip_unavailable=true clusters
// no matching indices and no concrete index requested - just skip it, no error
EsqlExecutionInfo.Cluster.Status status;
ShardSearchFailure failure;
if (c.equals(RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY)) {
// never mark local cluster as SKIPPED
status = EsqlExecutionInfo.Cluster.Status.SUCCESSFUL;
failure = null;
} else {
Expand All @@ -257,15 +256,7 @@ static void updateExecutionInfoWithClustersWithNoMatchingIndices(EsqlExecutionIn
}

// visible for testing
static boolean missingIndicesIsFatal(String clusterAlias, EsqlExecutionInfo executionInfo) {
// missing indices on local cluster is fatal only if a concrete index requested
if (clusterAlias.equals(RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY)) {
return concreteIndexRequested(executionInfo.getCluster(clusterAlias).getIndexExpression());
}
return executionInfo.getCluster(clusterAlias).isSkipUnavailable() == false;
}

private static boolean concreteIndexRequested(String indexExpression) {
static boolean concreteIndexRequested(String indexExpression) {
if (Strings.isNullOrBlank(indexExpression)) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ public void resolveAsMergedMapping(
public IndexResolution mergedMappings(String indexPattern, FieldCapabilitiesResponse fieldCapsResponse) {
assert ThreadPool.assertCurrentThreadPool(ThreadPool.Names.SEARCH_COORDINATION); // too expensive to run this on a transport worker
if (fieldCapsResponse.getIndexResponses().isEmpty()) {
// TODO in follow-on PR, handle the case where remotes were specified with non-existent indices, according to skip_unavailable
return IndexResolution.notFound(indexPattern);
}

Expand Down
Loading