|
@@ -10,13 +10,7 @@ import org.apache.logging.log4j.LogManager;
|
|
|
import org.apache.logging.log4j.Logger;
|
|
|
import org.apache.logging.log4j.message.ParameterizedMessage;
|
|
|
import org.elasticsearch.action.ActionListener;
|
|
|
-import org.elasticsearch.action.DocWriteResponse;
|
|
|
-import org.elasticsearch.action.bulk.BulkItemResponse;
|
|
|
-import org.elasticsearch.action.delete.DeleteAction;
|
|
|
-import org.elasticsearch.action.delete.DeleteRequest;
|
|
|
import org.elasticsearch.action.support.ActionFilters;
|
|
|
-import org.elasticsearch.action.support.IndicesOptions;
|
|
|
-import org.elasticsearch.action.support.WriteRequest;
|
|
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
|
|
import org.elasticsearch.action.support.master.AcknowledgedTransportMasterNodeAction;
|
|
|
import org.elasticsearch.client.Client;
|
|
@@ -27,35 +21,20 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
|
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
|
|
import org.elasticsearch.cluster.service.ClusterService;
|
|
|
import org.elasticsearch.common.inject.Inject;
|
|
|
-import org.elasticsearch.core.TimeValue;
|
|
|
-import org.elasticsearch.index.query.IdsQueryBuilder;
|
|
|
-import org.elasticsearch.index.query.QueryBuilder;
|
|
|
-import org.elasticsearch.index.query.QueryBuilders;
|
|
|
-import org.elasticsearch.index.reindex.AbstractBulkByScrollRequest;
|
|
|
-import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
|
|
-import org.elasticsearch.index.reindex.DeleteByQueryAction;
|
|
|
-import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
|
|
import org.elasticsearch.persistent.PersistentTasksCustomMetadata;
|
|
|
import org.elasticsearch.tasks.Task;
|
|
|
import org.elasticsearch.tasks.TaskId;
|
|
|
import org.elasticsearch.threadpool.ThreadPool;
|
|
|
import org.elasticsearch.transport.TransportService;
|
|
|
-import org.elasticsearch.xpack.core.ml.MlConfigIndex;
|
|
|
-import org.elasticsearch.xpack.core.ml.MlStatsIndex;
|
|
|
import org.elasticsearch.xpack.core.ml.MlTasks;
|
|
|
import org.elasticsearch.xpack.core.ml.action.DeleteDataFrameAnalyticsAction;
|
|
|
import org.elasticsearch.xpack.core.ml.action.StopDataFrameAnalyticsAction;
|
|
|
-import org.elasticsearch.xpack.core.ml.dataframe.DataFrameAnalyticsConfig;
|
|
|
import org.elasticsearch.xpack.core.ml.dataframe.DataFrameAnalyticsState;
|
|
|
-import org.elasticsearch.xpack.core.ml.dataframe.stats.Fields;
|
|
|
-import org.elasticsearch.xpack.core.ml.job.messages.Messages;
|
|
|
-import org.elasticsearch.xpack.core.ml.job.persistence.AnomalyDetectorsIndex;
|
|
|
import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
|
|
|
-import org.elasticsearch.xpack.ml.dataframe.StoredProgress;
|
|
|
import org.elasticsearch.xpack.ml.dataframe.persistence.DataFrameAnalyticsConfigProvider;
|
|
|
+import org.elasticsearch.xpack.ml.dataframe.persistence.DataFrameAnalyticsDeleter;
|
|
|
import org.elasticsearch.xpack.ml.notifications.DataFrameAnalyticsAuditor;
|
|
|
import org.elasticsearch.xpack.ml.process.MlMemoryTracker;
|
|
|
-import org.elasticsearch.xpack.ml.utils.MlIndicesUtils;
|
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
@@ -158,146 +137,15 @@ public class TransportDeleteDataFrameAnalyticsAction
|
|
|
// We clean up the memory tracker on delete because there is no stop; the task stops by itself
|
|
|
memoryTracker.removeDataFrameAnalyticsJob(id);
|
|
|
|
|
|
- // Step 4. Delete the config
|
|
|
- ActionListener<BulkByScrollResponse> deleteStatsHandler = ActionListener.wrap(
|
|
|
- bulkByScrollResponse -> {
|
|
|
- if (bulkByScrollResponse.isTimedOut()) {
|
|
|
- logger.warn("[{}] DeleteByQuery for stats timed out", id);
|
|
|
- }
|
|
|
- if (bulkByScrollResponse.getBulkFailures().isEmpty() == false) {
|
|
|
- logger.warn("[{}] {} failures and {} conflicts encountered while running DeleteByQuery for stats", id,
|
|
|
- bulkByScrollResponse.getBulkFailures().size(), bulkByScrollResponse.getVersionConflicts());
|
|
|
- for (BulkItemResponse.Failure failure : bulkByScrollResponse.getBulkFailures()) {
|
|
|
- logger.warn("[{}] DBQ failure: {}", id, failure);
|
|
|
- }
|
|
|
- }
|
|
|
- deleteConfig(parentTaskClient, id, listener);
|
|
|
- },
|
|
|
- failure -> {
|
|
|
- logger.warn(new ParameterizedMessage("[{}] failed to remove stats", id), ExceptionsHelper.unwrapCause(failure));
|
|
|
- deleteConfig(parentTaskClient, id, listener);
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- // Step 3. Delete job docs from stats index
|
|
|
- ActionListener<BulkByScrollResponse> deleteStateHandler = ActionListener.wrap(
|
|
|
- bulkByScrollResponse -> {
|
|
|
- if (bulkByScrollResponse.isTimedOut()) {
|
|
|
- logger.warn("[{}] DeleteByQuery for state timed out", id);
|
|
|
- }
|
|
|
- if (bulkByScrollResponse.getBulkFailures().isEmpty() == false) {
|
|
|
- logger.warn("[{}] {} failures and {} conflicts encountered while running DeleteByQuery for state", id,
|
|
|
- bulkByScrollResponse.getBulkFailures().size(), bulkByScrollResponse.getVersionConflicts());
|
|
|
- for (BulkItemResponse.Failure failure : bulkByScrollResponse.getBulkFailures()) {
|
|
|
- logger.warn("[{}] DBQ failure: {}", id, failure);
|
|
|
- }
|
|
|
- }
|
|
|
- deleteStats(parentTaskClient, id, request.timeout(), deleteStatsHandler);
|
|
|
- },
|
|
|
- listener::onFailure
|
|
|
- );
|
|
|
-
|
|
|
- // Step 2. Delete state
|
|
|
- ActionListener<DataFrameAnalyticsConfig> configListener = ActionListener.wrap(
|
|
|
- config -> deleteState(parentTaskClient, config, request.timeout(), deleteStateHandler),
|
|
|
- listener::onFailure
|
|
|
- );
|
|
|
-
|
|
|
- // Step 1. Get the config to check if it exists
|
|
|
- configProvider.get(id, configListener);
|
|
|
- }
|
|
|
-
|
|
|
- private void deleteConfig(ParentTaskAssigningClient parentTaskClient, String id, ActionListener<AcknowledgedResponse> listener) {
|
|
|
- DeleteRequest deleteRequest = new DeleteRequest(MlConfigIndex.indexName());
|
|
|
- deleteRequest.id(DataFrameAnalyticsConfig.documentId(id));
|
|
|
- deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
|
|
|
- executeAsyncWithOrigin(parentTaskClient, ML_ORIGIN, DeleteAction.INSTANCE, deleteRequest, ActionListener.wrap(
|
|
|
- deleteResponse -> {
|
|
|
- if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
|
|
|
- listener.onFailure(ExceptionsHelper.missingDataFrameAnalytics(id));
|
|
|
- return;
|
|
|
- }
|
|
|
- assert deleteResponse.getResult() == DocWriteResponse.Result.DELETED;
|
|
|
- logger.info("[{}] Deleted", id);
|
|
|
- auditor.info(id, Messages.DATA_FRAME_ANALYTICS_AUDIT_DELETED);
|
|
|
- listener.onResponse(AcknowledgedResponse.TRUE);
|
|
|
+ configProvider.get(id, ActionListener.wrap(
|
|
|
+ config -> {
|
|
|
+ DataFrameAnalyticsDeleter deleter = new DataFrameAnalyticsDeleter(parentTaskClient, auditor);
|
|
|
+ deleter.deleteAllDocuments(config, request.timeout(), listener);
|
|
|
},
|
|
|
listener::onFailure
|
|
|
));
|
|
|
}
|
|
|
|
|
|
- private void deleteState(ParentTaskAssigningClient parentTaskClient,
|
|
|
- DataFrameAnalyticsConfig config,
|
|
|
- TimeValue timeout,
|
|
|
- ActionListener<BulkByScrollResponse> listener) {
|
|
|
- ActionListener<Boolean> deleteModelStateListener = ActionListener.wrap(
|
|
|
- r -> executeDeleteByQuery(
|
|
|
- parentTaskClient,
|
|
|
- AnomalyDetectorsIndex.jobStateIndexPattern(),
|
|
|
- QueryBuilders.idsQuery().addIds(StoredProgress.documentId(config.getId())),
|
|
|
- timeout,
|
|
|
- listener
|
|
|
- )
|
|
|
- , listener::onFailure
|
|
|
- );
|
|
|
-
|
|
|
- deleteModelState(parentTaskClient, config, timeout, 1, deleteModelStateListener);
|
|
|
- }
|
|
|
-
|
|
|
- private void deleteModelState(ParentTaskAssigningClient parentTaskClient,
|
|
|
- DataFrameAnalyticsConfig config,
|
|
|
- TimeValue timeout,
|
|
|
- int docNum,
|
|
|
- ActionListener<Boolean> listener) {
|
|
|
- if (config.getAnalysis().persistsState() == false) {
|
|
|
- listener.onResponse(true);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- IdsQueryBuilder query = QueryBuilders.idsQuery().addIds(config.getAnalysis().getStateDocIdPrefix(config.getId()) + docNum);
|
|
|
- executeDeleteByQuery(
|
|
|
- parentTaskClient,
|
|
|
- AnomalyDetectorsIndex.jobStateIndexPattern(),
|
|
|
- query,
|
|
|
- timeout,
|
|
|
- ActionListener.wrap(
|
|
|
- response -> {
|
|
|
- if (response.getDeleted() > 0) {
|
|
|
- deleteModelState(parentTaskClient, config, timeout, docNum + 1, listener);
|
|
|
- return;
|
|
|
- }
|
|
|
- listener.onResponse(true);
|
|
|
- },
|
|
|
- listener::onFailure
|
|
|
- )
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- private void deleteStats(ParentTaskAssigningClient parentTaskClient,
|
|
|
- String jobId,
|
|
|
- TimeValue timeout,
|
|
|
- ActionListener<BulkByScrollResponse> listener) {
|
|
|
- executeDeleteByQuery(
|
|
|
- parentTaskClient,
|
|
|
- MlStatsIndex.indexPattern(),
|
|
|
- QueryBuilders.termQuery(Fields.JOB_ID.getPreferredName(), jobId),
|
|
|
- timeout,
|
|
|
- listener
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- private void executeDeleteByQuery(ParentTaskAssigningClient parentTaskClient, String index, QueryBuilder query, TimeValue timeout,
|
|
|
- ActionListener<BulkByScrollResponse> listener) {
|
|
|
- DeleteByQueryRequest request = new DeleteByQueryRequest(index);
|
|
|
- request.setQuery(query);
|
|
|
- request.setIndicesOptions(MlIndicesUtils.addIgnoreUnavailable(IndicesOptions.lenientExpandOpen()));
|
|
|
- request.setSlices(AbstractBulkByScrollRequest.AUTO_SLICES);
|
|
|
- request.setAbortOnVersionConflict(false);
|
|
|
- request.setRefresh(true);
|
|
|
- request.setTimeout(timeout);
|
|
|
- executeAsyncWithOrigin(parentTaskClient, ML_ORIGIN, DeleteByQueryAction.INSTANCE, request, listener);
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
protected ClusterBlockException checkBlock(DeleteDataFrameAnalyticsAction.Request request, ClusterState state) {
|
|
|
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|