|
8 | 8 |
|
9 | 9 | import org.apache.logging.log4j.LogManager;
|
10 | 10 | import org.apache.logging.log4j.Logger;
|
| 11 | +import org.apache.lucene.search.TotalHits; |
11 | 12 | import org.elasticsearch.ElasticsearchException;
|
12 | 13 | import org.elasticsearch.action.ActionListener;
|
13 | 14 | import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
14 | 15 | import org.elasticsearch.action.admin.indices.readonly.AddIndexBlockRequest;
|
15 | 16 | import org.elasticsearch.action.admin.indices.readonly.AddIndexBlockResponse;
|
16 | 17 | import org.elasticsearch.action.admin.indices.readonly.TransportAddIndexBlockAction;
|
| 18 | +import org.elasticsearch.action.admin.indices.refresh.RefreshAction; |
| 19 | +import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; |
17 | 20 | import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
| 21 | +import org.elasticsearch.action.search.SearchRequest; |
18 | 22 | import org.elasticsearch.action.support.ActionFilters;
|
19 | 23 | import org.elasticsearch.action.support.HandledTransportAction;
|
20 | 24 | import org.elasticsearch.action.support.IndicesOptions;
|
|
26 | 30 | import org.elasticsearch.cluster.service.ClusterService;
|
27 | 31 | import org.elasticsearch.common.settings.Setting;
|
28 | 32 | import org.elasticsearch.common.settings.Settings;
|
| 33 | +import org.elasticsearch.core.Assertions; |
29 | 34 | import org.elasticsearch.core.TimeValue;
|
30 | 35 | import org.elasticsearch.index.IndexSettings;
|
31 | 36 | import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
32 | 37 | import org.elasticsearch.index.reindex.ReindexAction;
|
33 | 38 | import org.elasticsearch.index.reindex.ReindexRequest;
|
34 | 39 | import org.elasticsearch.injection.guice.Inject;
|
| 40 | +import org.elasticsearch.search.builder.SearchSourceBuilder; |
35 | 41 | import org.elasticsearch.tasks.Task;
|
36 | 42 | import org.elasticsearch.tasks.TaskId;
|
37 | 43 | import org.elasticsearch.threadpool.ThreadPool;
|
@@ -138,6 +144,7 @@ protected void doExecute(
|
138 | 144 | .<AcknowledgedResponse>andThen(l -> createIndex(sourceIndex, destIndexName, l, taskId))
|
139 | 145 | .<BulkByScrollResponse>andThen(l -> reindex(sourceIndexName, destIndexName, l, taskId))
|
140 | 146 | .<AcknowledgedResponse>andThen(l -> copyOldSourceSettingsToDest(settingsBefore, destIndexName, l, taskId))
|
| 147 | + .<AcknowledgedResponse>andThen(l -> sanityCheck(sourceIndexName, destIndexName, l, taskId)) |
141 | 148 | .andThenApply(ignored -> new ReindexDataStreamIndexAction.Response(destIndexName))
|
142 | 149 | .addListener(listener);
|
143 | 150 | }
|
@@ -220,21 +227,6 @@ void reindex(String sourceIndexName, String destIndexName, ActionListener<BulkBy
|
220 | 227 | client.execute(ReindexAction.INSTANCE, reindexRequest, listener);
|
221 | 228 | }
|
222 | 229 |
|
223 |
| - private void addBlockIfFromSource( |
224 |
| - IndexMetadata.APIBlock block, |
225 |
| - Settings settingsBefore, |
226 |
| - String destIndexName, |
227 |
| - ActionListener<AddIndexBlockResponse> listener, |
228 |
| - TaskId parentTaskId |
229 |
| - ) { |
230 |
| - if (settingsBefore.getAsBoolean(block.settingName(), false)) { |
231 |
| - var errorMessage = String.format(Locale.ROOT, "Add [%s] block to index [%s] was not acknowledged", block.name(), destIndexName); |
232 |
| - addBlockToIndex(block, destIndexName, failIfNotAcknowledged(listener, errorMessage), parentTaskId); |
233 |
| - } else { |
234 |
| - listener.onResponse(null); |
235 |
| - } |
236 |
| - } |
237 |
| - |
238 | 230 | private void updateSettings(
|
239 | 231 | String index,
|
240 | 232 | Settings.Builder settings,
|
@@ -302,4 +294,50 @@ private void addBlockToIndex(
|
302 | 294 | addIndexBlockRequest.setParentTask(parentTaskId);
|
303 | 295 | client.admin().indices().execute(TransportAddIndexBlockAction.TYPE, addIndexBlockRequest, listener);
|
304 | 296 | }
|
| 297 | + |
| 298 | + private void getIndexDocCount(String index, TaskId parentTaskId, ActionListener<Long> listener) { |
| 299 | + SearchRequest countRequest = new SearchRequest(index); |
| 300 | + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().size(0).trackTotalHits(true); |
| 301 | + countRequest.allowPartialSearchResults(false); |
| 302 | + countRequest.source(searchSourceBuilder); |
| 303 | + countRequest.setParentTask(parentTaskId); |
| 304 | + client.search(countRequest, listener.delegateFailure((delegate, response) -> { |
| 305 | + var totalHits = response.getHits().getTotalHits(); |
| 306 | + assert totalHits.relation == TotalHits.Relation.EQUAL_TO; |
| 307 | + delegate.onResponse(totalHits.value); |
| 308 | + })); |
| 309 | + } |
| 310 | + |
| 311 | + private void sanityCheck( |
| 312 | + String sourceIndexName, |
| 313 | + String destIndexName, |
| 314 | + ActionListener<AcknowledgedResponse> listener, |
| 315 | + TaskId parentTaskId |
| 316 | + ) { |
| 317 | + if (Assertions.ENABLED) { |
| 318 | + logger.debug("Comparing source [{}] and dest [{}] doc counts", sourceIndexName, destIndexName); |
| 319 | + client.execute( |
| 320 | + RefreshAction.INSTANCE, |
| 321 | + new RefreshRequest(destIndexName), |
| 322 | + listener.delegateFailureAndWrap((delegate, ignored) -> { |
| 323 | + getIndexDocCount(sourceIndexName, parentTaskId, delegate.delegateFailureAndWrap((delegate1, sourceCount) -> { |
| 324 | + getIndexDocCount(destIndexName, parentTaskId, delegate1.delegateFailureAndWrap((delegate2, destCount) -> { |
| 325 | + assert sourceCount == destCount |
| 326 | + : String.format( |
| 327 | + Locale.ROOT, |
| 328 | + "source index [%s] has %d docs and dest [%s] has %d docs", |
| 329 | + sourceIndexName, |
| 330 | + sourceCount, |
| 331 | + destIndexName, |
| 332 | + destCount |
| 333 | + ); |
| 334 | + delegate2.onResponse(null); |
| 335 | + })); |
| 336 | + })); |
| 337 | + }) |
| 338 | + ); |
| 339 | + } else { |
| 340 | + listener.onResponse(null); |
| 341 | + } |
| 342 | + } |
305 | 343 | }
|
0 commit comments