Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
6 changes: 6 additions & 0 deletions docs/changelog/128361.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 128361
summary: The follower index should wait until the time series end time passes before unfollowing the leader index.
area: ILM+SLM
type: bug
issues:
- 128129
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
Expand Down Expand Up @@ -571,7 +570,7 @@ public void testILMUnfollowFailsToRemoveRetentionLeases() throws Exception {
}
}

@SuppressWarnings({ "checkstyle:LineLength", "unchecked" })
@SuppressWarnings("unchecked")
public void testTsdbLeaderIndexRolloverAndSyncAfterWaitUntilEndTime() throws Exception {
String indexPattern = "tsdb-index-";
String dataStream = "tsdb-index-cpu";
Expand All @@ -583,12 +582,12 @@ public void testTsdbLeaderIndexRolloverAndSyncAfterWaitUntilEndTime() throws Exc
templateRequest.setJsonEntity(Strings.format(TSDB_INDEX_TEMPLATE, indexPattern, policyName));
assertOK(client().performRequest(templateRequest));
} else if ("follow".equals(targetCluster)) {
putILMPolicy(policyName, null, 1, null);
putUnfollowOnlyPolicy(client(), policyName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar here, could you add a comment to explain why we only want Unfollow action?


Request createAutoFollowRequest = new Request("PUT", "/_ccr/auto_follow/tsdb_index_auto_follow_pattern");
createAutoFollowRequest.setJsonEntity("""
{
"leader_index_patterns": [ ".ds-tsdb-index-*" ],
"leader_index_patterns": [ "tsdb-index-*" ],
"remote_cluster": "leader_cluster",
"read_poll_timeout": "1000ms",
"follow_index_pattern": "{{leader_index}}"
Expand All @@ -600,28 +599,19 @@ public void testTsdbLeaderIndexRolloverAndSyncAfterWaitUntilEndTime() throws Exc
index(leaderClient, dataStream, "", "@timestamp", now, "volume", 11.0, "metricset", randomAlphaOfLength(5));

String backingIndexName = getDataStreamBackingIndexNames(leaderClient, "tsdb-index-cpu").get(0);
assertBusy(() -> { assertOK(client().performRequest(new Request("HEAD", "/" + backingIndexName))); });

// rollover
Request rolloverRequest = new Request("POST", "/" + dataStream + "/_rollover");
rolloverRequest.setJsonEntity("""
{
"conditions": {
"max_docs": "1"
}
}""");
leaderClient.performRequest(rolloverRequest);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment to explain why we need to wait for ILM to rollover instead of manual rollover?

Copy link
Contributor Author

@happysubin happysubin Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course! I’ll add comments explaining why we did it this way!

assertBusy(() -> assertOK(client().performRequest(new Request("HEAD", "/" + backingIndexName))));

assertBusy(() -> {
Map<String, Object> indexExplanation = explainIndex(client(), backingIndexName);
assertThat(
"index must wait in the " + WaitUntilTimeSeriesEndTimePassesStep.NAME + " until its end time lapses",
explainIndex(client(), backingIndexName).get("step"),
indexExplanation.get("step"),
is(WaitUntilTimeSeriesEndTimePassesStep.NAME)
);

assertThat(explainIndex(client(), backingIndexName).get("step_info"), is(notNullValue()));
assertThat(indexExplanation.get("step_info"), is(notNullValue()));
assertThat(
(String) ((Map<String, Object>) explainIndex(client(), backingIndexName).get("step_info")).get("message"),
(String) ((Map<String, Object>) indexExplanation.get("step_info")).get("message"),
containsString("Waiting until the index's time series end time lapses")
);
}, 30, TimeUnit.SECONDS);
Expand Down Expand Up @@ -967,15 +957,7 @@ private static String getShrinkIndexName(RestClient client, String originalIndex
}

private static Map<String, Object> explainIndex(RestClient client, String indexName) throws IOException {
RequestOptions consumeWarningsOptions = RequestOptions.DEFAULT.toBuilder()
.setWarningsHandler(warnings -> warnings.isEmpty() == false && List.of("""
[indices.lifecycle.rollover.only_if_has_documents] setting was deprecated in Elasticsearch \
and will be removed in a future release. \
See the deprecation documentation for the next major version.""").equals(warnings) == false)
.build();

Request explainRequest = new Request("GET", indexName + "/_ilm/explain");
explainRequest.setOptions(consumeWarningsOptions);
Response response = client.performRequest(explainRequest);
Map<String, Object> responseMap;
try (InputStream is = response.getEntity().getContent()) {
Expand All @@ -991,7 +973,6 @@ private static int getDocCount(RestClient client, String indexName) throws IOExc
Request countRequest = new Request("GET", "/" + indexName + "/_count");
Response response = client.performRequest(countRequest);
Map<String, Object> result = entityAsMap(response);
System.out.println("result = " + result);
return (int) result.get("count");
}
}
Loading