Skip to content

Commit 864de68

Browse files
committedJun 9, 2024
rollover custom result index with conditions
Signed-off-by: Jackie Han <jkhanjob@gmail.com>
1 parent 051acf0 commit 864de68

File tree

2 files changed

+251
-19
lines changed

2 files changed

+251
-19
lines changed
 

‎src/main/java/org/opensearch/timeseries/indices/IndexManagement.java

+97-17
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
package org.opensearch.timeseries.indices;
1313

1414
import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;
15+
import static org.opensearch.forecast.constant.ForecastCommonName.CUSTOM_RESULT_INDEX_PREFIX;
1516
import static org.opensearch.timeseries.util.RestHandlerUtils.createXContentParserFromRegistry;
1617

1718
import java.io.IOException;
@@ -51,6 +52,7 @@
5152
import org.opensearch.action.search.SearchRequest;
5253
import org.opensearch.action.support.GroupedActionListener;
5354
import org.opensearch.action.support.IndicesOptions;
55+
import org.opensearch.ad.constant.ADCommonName;
5456
import org.opensearch.client.AdminClient;
5557
import org.opensearch.client.Client;
5658
import org.opensearch.cluster.LocalNodeClusterManagerListener;
@@ -66,6 +68,8 @@
6668
import org.opensearch.core.action.ActionListener;
6769
import org.opensearch.core.common.Strings;
6870
import org.opensearch.core.common.bytes.BytesArray;
71+
import org.opensearch.core.common.unit.ByteSizeUnit;
72+
import org.opensearch.core.common.unit.ByteSizeValue;
6973
import org.opensearch.core.xcontent.NamedXContentRegistry;
7074
import org.opensearch.core.xcontent.XContentParser;
7175
import org.opensearch.core.xcontent.XContentParser.Token;
@@ -298,7 +302,8 @@ protected void deleteOldHistoryIndices(String indexPattern, TimeValue historyRet
298302
long latest = Long.MIN_VALUE;
299303
for (IndexMetadata indexMetaData : clusterStateResponse.getState().metadata().indices().values()) {
300304
long creationTime = indexMetaData.getCreationDate();
301-
if ((Instant.now().toEpochMilli() - creationTime) > historyRetentionPeriod.millis()) {
305+
long indexAgeMillis = Instant.now().toEpochMilli() - creationTime;
306+
if (indexAgeMillis > historyRetentionPeriod.millis()) {
302307
String indexName = indexMetaData.getIndex().getName();
303308
candidates.add(indexName);
304309
if (latest < creationTime) {
@@ -1077,7 +1082,7 @@ public void onClusterManager() {
10771082

10781083
// schedule the next rollover for approx MAX_AGE later
10791084
scheduledRollover = threadPool
1080-
.scheduleWithFixedDelay(() -> rolloverAndDeleteHistoryIndex(), historyRolloverPeriod, executorName());
1085+
.scheduleWithFixedDelay(() -> rolloverAndDeleteHistoryIndex(), TimeValue.timeValueMinutes(1), executorName());
10811086
} catch (Exception e) {
10821087
// This should be run on cluster startup
10831088
logger.error("Error rollover result indices. " + "Can't rollover result until clusterManager node is restarted.", e);
@@ -1100,6 +1105,7 @@ protected void rescheduleRollover() {
11001105
if (scheduledRollover != null) {
11011106
scheduledRollover.cancel();
11021107
}
1108+
11031109
scheduledRollover = threadPool
11041110
.scheduleWithFixedDelay(() -> rolloverAndDeleteHistoryIndex(), historyRolloverPeriod, executorName());
11051111
}
@@ -1234,35 +1240,109 @@ protected void rolloverAndDeleteHistoryIndex(
12341240
String rolloverIndexPattern,
12351241
IndexType resultIndex
12361242
) {
1237-
if (!doesDefaultResultIndexExist()) {
1238-
return;
1243+
// build rollover request for default result index
1244+
RolloverRequest defaultResultIndexRolloverRequest = buildRolloverRequest(resultIndexAlias, rolloverIndexPattern);
1245+
defaultResultIndexRolloverRequest.addMaxIndexDocsCondition(historyMaxDocs * getNumberOfPrimaryShards());
1246+
1247+
// get config files that have custom result index alias to perform rollover on
1248+
getConfigsWithCustomResultIndexAlias(ActionListener.wrap(candidateResultAliases -> {
1249+
if (candidateResultAliases == null || candidateResultAliases.isEmpty()) {
1250+
// no custom result index alias found
1251+
if (!doesDefaultResultIndexExist()) {
1252+
// no default result index found either
1253+
return;
1254+
}
1255+
// perform rollover and delete on default result index
1256+
proceedWithDefaultRolloverAndDelete(
1257+
resultIndexAlias,
1258+
defaultResultIndexRolloverRequest,
1259+
allResultIndicesPattern,
1260+
resultIndex
1261+
);
1262+
logger.info("Candidate custom result indices are empty.");
1263+
return;
1264+
}
1265+
1266+
// perform rollover and delete on found custom result index alias
1267+
candidateResultAliases.forEach(config -> handleCustomResultIndex(config, resultIndex));
1268+
1269+
}, e -> {
1270+
logger.error("Failed to get configs with custom result index alias.", e);
1271+
// perform rollover and delete on default result index if getting error on getting custom result index alias
1272+
proceedWithDefaultRolloverAndDelete(resultIndexAlias, defaultResultIndexRolloverRequest, allResultIndicesPattern, resultIndex);
1273+
}));
1274+
}
1275+
1276+
private void handleCustomResultIndex(Config config, IndexType resultIndex) {
1277+
RolloverRequest rolloverRequest = buildRolloverRequest(
1278+
config.getCustomResultIndexOrAlias(),
1279+
getCustomResultIndexPattern(config.getCustomResultIndexOrAlias())
1280+
);
1281+
1282+
// add rollover conditions if found in config
1283+
if (config.getCustomResultIndexMinAge() != null) {
1284+
rolloverRequest.addMaxIndexAgeCondition(TimeValue.timeValueDays(config.getCustomResultIndexMinAge()));
1285+
}
1286+
if (config.getCustomResultIndexMinSize() != null) {
1287+
rolloverRequest.addMaxIndexSizeCondition(new ByteSizeValue(config.getCustomResultIndexMinSize(), ByteSizeUnit.MB));
12391288
}
12401289

1241-
// We have to pass null for newIndexName in order to get Elastic to increment the index count.
1242-
RolloverRequest rollOverRequest = new RolloverRequest(resultIndexAlias, null);
1290+
// perform rollover and delete on custom result index alias
1291+
proceedWithRolloverAndDelete(
1292+
config.getCustomResultIndexOrAlias(),
1293+
rolloverRequest,
1294+
getAllCustomResultIndexPattern(config.getCustomResultIndexOrAlias()),
1295+
resultIndex,
1296+
config.getCustomResultIndexTTL()
1297+
);
1298+
}
12431299

1300+
private void proceedWithDefaultRolloverAndDelete(
1301+
String resultIndexAlias,
1302+
RolloverRequest rolloverRequest,
1303+
String allResultIndicesPattern,
1304+
IndexType resultIndex
1305+
) {
1306+
proceedWithRolloverAndDelete(resultIndexAlias, rolloverRequest, allResultIndicesPattern, resultIndex, null);
1307+
}
1308+
1309+
private RolloverRequest buildRolloverRequest(String resultIndexAlias, String rolloverIndexPattern) {
1310+
RolloverRequest rollOverRequest = new RolloverRequest(resultIndexAlias, null);
12441311
CreateIndexRequest createRequest = rollOverRequest.getCreateIndexRequest();
12451312

12461313
createRequest.index(rolloverIndexPattern).mapping(resultMapping, XContentType.JSON);
1247-
12481314
choosePrimaryShards(createRequest, true);
12491315

1250-
rollOverRequest.addMaxIndexDocsCondition(historyMaxDocs * getNumberOfPrimaryShards());
1316+
return rollOverRequest;
1317+
}
1318+
1319+
private void proceedWithRolloverAndDelete(
1320+
String resultIndexAlias,
1321+
RolloverRequest rollOverRequest,
1322+
String allResultIndicesPattern,
1323+
IndexType resultIndex,
1324+
Integer customResultIndexTtl
1325+
) {
12511326
adminClient.indices().rolloverIndex(rollOverRequest, ActionListener.wrap(response -> {
12521327
if (!response.isRolledOver()) {
12531328
logger.warn("{} not rolled over. Conditions were: {}", resultIndexAlias, response.getConditionStatus());
12541329
} else {
1255-
IndexState indexStatetate = indexStates.computeIfAbsent(resultIndex, k -> new IndexState(k.getMapping()));
1256-
indexStatetate.mappingUpToDate = true;
1330+
IndexState indexState = indexStates.computeIfAbsent(resultIndex, k -> new IndexState(k.getMapping()));
1331+
indexState.mappingUpToDate = true;
12571332
logger.info("{} rolled over. Conditions were: {}", resultIndexAlias, response.getConditionStatus());
1258-
deleteOldHistoryIndices(allResultIndicesPattern, historyRetentionPeriod);
1333+
if (resultIndexAlias.startsWith(ADCommonName.CUSTOM_RESULT_INDEX_PREFIX)
1334+
|| resultIndexAlias.startsWith(CUSTOM_RESULT_INDEX_PREFIX)) {
1335+
// handle custom result index deletion
1336+
if (customResultIndexTtl != null) {
1337+
deleteOldHistoryIndices(allResultIndicesPattern, TimeValue.timeValueHours(customResultIndexTtl * 24));
1338+
1339+
}
1340+
} else {
1341+
// handle default result index deletion
1342+
deleteOldHistoryIndices(allResultIndicesPattern, historyRetentionPeriod);
1343+
}
12591344
}
1260-
}, exception -> {
1261-
// e.g., we may roll over too often. Since the index pattern is opensearch-ad-plugin-result-d-history-{now/d}-000001,
1262-
// we cannot roll over twice in the same day as the index with the same name exists. We will get
1263-
// resource_already_exists_exception.
1264-
logger.error("Fail to roll over result index", exception);
1265-
}));
1345+
}, exception -> { logger.error("Fail to roll over result index", exception); }));
12661346
}
12671347

12681348
protected void initResultIndexDirectly(

0 commit comments

Comments
 (0)