-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Determine remote cluster version #142494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Determine remote cluster version #142494
Changes from all commits
28bc7f9
9427763
3430f18
66f7deb
a434f0d
7516540
1739e0f
a805729
d5471f0
b0c22a9
6b86337
61b187a
13bdc0b
1dd0afc
9cf2f11
460140c
5fd8ab0
298f6fb
6192133
ec2517b
3ba1670
363f2c2
2a4e999
5899ba4
04fe410
8552f60
40ed11f
1700728
6f6e96a
5252944
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| import org.apache.http.message.BasicHeader; | ||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
| import org.elasticsearch.Version; | ||
| import org.elasticsearch.action.ActionListener; | ||
| import org.elasticsearch.action.ActionListenerResponseHandler; | ||
| import org.elasticsearch.action.DocWriteRequest; | ||
|
|
@@ -53,11 +54,13 @@ | |
| import org.elasticsearch.index.reindex.PaginatedHitSource; | ||
| import org.elasticsearch.index.reindex.ReindexAction; | ||
| import org.elasticsearch.index.reindex.ReindexRequest; | ||
| import org.elasticsearch.index.reindex.RejectAwareActionListener; | ||
| import org.elasticsearch.index.reindex.RemoteInfo; | ||
| import org.elasticsearch.index.reindex.ResumeBulkByScrollRequest; | ||
| import org.elasticsearch.index.reindex.ResumeBulkByScrollResponse; | ||
| import org.elasticsearch.index.reindex.ResumeReindexAction; | ||
| import org.elasticsearch.index.reindex.WorkerBulkByScrollTaskState; | ||
| import org.elasticsearch.reindex.remote.RemoteReindexingUtils; | ||
| import org.elasticsearch.reindex.remote.RemoteScrollablePaginatedHitSource; | ||
| import org.elasticsearch.script.CtxMap; | ||
| import org.elasticsearch.script.ReindexMetadata; | ||
|
|
@@ -83,12 +86,15 @@ | |
| import java.util.concurrent.atomic.AtomicInteger; | ||
| import java.util.concurrent.atomic.AtomicReference; | ||
| import java.util.function.BiFunction; | ||
| import java.util.function.Consumer; | ||
| import java.util.function.LongSupplier; | ||
| import java.util.function.Supplier; | ||
|
|
||
| import static java.util.Collections.emptyList; | ||
| import static java.util.Collections.synchronizedList; | ||
| import static org.elasticsearch.common.BackoffPolicy.exponentialBackoff; | ||
| import static org.elasticsearch.index.VersionType.INTERNAL; | ||
| import static org.elasticsearch.reindex.ReindexPlugin.REINDEX_PIT_SEARCH_ENABLED; | ||
|
|
||
| public class Reindexer { | ||
|
|
||
|
|
@@ -143,33 +149,113 @@ public void execute(BulkByScrollTask task, ReindexRequest request, Client bulkCl | |
| // for update-by-query and delete-by-query | ||
| final ActionListener<BulkByScrollResponse> listenerWithRelocations = listenerWithRelocations(task, request, listener); | ||
|
|
||
| BulkByPaginatedSearchParallelizationHelper.executeSlicedAction( | ||
| task, | ||
| request, | ||
| ReindexAction.INSTANCE, | ||
| listenerWithRelocations, | ||
| client, | ||
| clusterService.localNode(), | ||
| () -> { | ||
| ParentTaskAssigningClient assigningClient = new ParentTaskAssigningClient(client, clusterService.localNode(), task); | ||
| ParentTaskAssigningClient assigningBulkClient = new ParentTaskAssigningClient(bulkClient, clusterService.localNode(), task); | ||
| AsyncIndexBySearchAction searchAction = new AsyncIndexBySearchAction( | ||
| task, | ||
| logger, | ||
| assigningClient, | ||
| assigningBulkClient, | ||
| threadPool, | ||
| scriptService, | ||
| projectResolver.getProjectState(clusterService.state()), | ||
| reindexSslConfig, | ||
| request, | ||
| workerListenerWithRelocationAndMetrics(listenerWithRelocations, startTime, request.getRemoteInfo() != null) | ||
| Consumer<Version> workerAction = remoteVersion -> { | ||
| ParentTaskAssigningClient assigningClient = new ParentTaskAssigningClient(client, clusterService.localNode(), task); | ||
| ParentTaskAssigningClient assigningBulkClient = new ParentTaskAssigningClient(bulkClient, clusterService.localNode(), task); | ||
| AsyncIndexBySearchAction searchAction = new AsyncIndexBySearchAction( | ||
| task, | ||
| logger, | ||
| assigningClient, | ||
| assigningBulkClient, | ||
| threadPool, | ||
| scriptService, | ||
| projectResolver.getProjectState(clusterService.state()), | ||
| reindexSslConfig, | ||
| request, | ||
| workerListenerWithRelocationAndMetrics(listenerWithRelocations, startTime, request.getRemoteInfo() != null), | ||
| remoteVersion | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unchanged, except I pass the |
||
| ); | ||
| searchAction.start(); | ||
| }; | ||
|
|
||
| /** | ||
| * If this is a request to reindex from remote, then we need to determine the remote version prior to execution | ||
| * NB {@link ReindexRequest} forbids remote requests and slices > 1, so we're guaranteed to be running on the only slice | ||
| */ | ||
| if (REINDEX_PIT_SEARCH_ENABLED && request.getRemoteInfo() != null) { | ||
| lookupRemoteVersionAndExecute(task, request, listenerWithRelocations, workerAction); | ||
| } else { | ||
| BulkByPaginatedSearchParallelizationHelper.executeSlicedAction( | ||
| task, | ||
| request, | ||
| ReindexAction.INSTANCE, | ||
| listenerWithRelocations, | ||
| client, | ||
| clusterService.localNode(), | ||
| null, | ||
| workerAction | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Looks up the remote cluster version when reindexing from a remote source, then runs the sliced action with that version. | ||
| * The RestClient used for the lookup is closed after the callback; closing must happen on a thread other than the | ||
| * RestClient's own thread pool to avoid shutdown failures. | ||
| */ | ||
| private void lookupRemoteVersionAndExecute( | ||
| BulkByScrollTask task, | ||
| ReindexRequest request, | ||
| ActionListener<BulkByScrollResponse> listenerWithRelocations, | ||
| Consumer<Version> workerAction | ||
| ) { | ||
samxbr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| RemoteInfo remoteInfo = request.getRemoteInfo(); | ||
| assert reindexSslConfig != null : "Reindex ssl config must be set"; | ||
| RestClient restClient = buildRestClient(remoteInfo, reindexSslConfig, task.getId(), synchronizedList(new ArrayList<>())); | ||
| RejectAwareActionListener<Version> rejectAwareListener = new RejectAwareActionListener<>() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently the remote version lookup has retries as part of starting the search. It'd be nice to add retries here too?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch - will add now |
||
| @Override | ||
| public void onResponse(Version version) { | ||
| closeRestClientAndRun( | ||
| restClient, | ||
| () -> BulkByPaginatedSearchParallelizationHelper.executeSlicedAction( | ||
| task, | ||
| request, | ||
| ReindexAction.INSTANCE, | ||
| listenerWithRelocations, | ||
| client, | ||
| clusterService.localNode(), | ||
| version, | ||
| workerAction | ||
| ) | ||
| ); | ||
| searchAction.start(); | ||
| } | ||
|
|
||
| @Override | ||
| public void onFailure(Exception e) { | ||
| closeRestClientAndRun(restClient, () -> listenerWithRelocations.onFailure(e)); | ||
| } | ||
|
|
||
| @Override | ||
| public void onRejection(Exception e) { | ||
| closeRestClientAndRun(restClient, () -> listenerWithRelocations.onFailure(e)); | ||
| } | ||
| }; | ||
| RemoteReindexingUtils.lookupRemoteVersionWithRetries( | ||
| logger, | ||
| exponentialBackoff(request.getRetryBackoffInitialTime(), request.getMaxRetries()), | ||
| threadPool, | ||
| restClient, | ||
| // TODO - Do we want to pass in a countRetry runnable here to count the number of times we retry? | ||
| // https://github.com/elastic/elasticsearch-team/issues/2382 | ||
| rejectAwareListener | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Closes the RestClient on the generic thread pool (to avoid closing from the client's own thread), then runs the given action. | ||
| */ | ||
| private void closeRestClientAndRun(RestClient restClient, Runnable onCompletion) { | ||
| threadPool.generic().submit(() -> { | ||
| try { | ||
| restClient.close(); | ||
| } catch (IOException e) { | ||
| logger.warn("Failed to close RestClient after version lookup", e); | ||
| } finally { | ||
| onCompletion.run(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** Wraps the listener with metrics tracking and relocation handling (if applicable). Visible for testing. */ | ||
| ActionListener<BulkByScrollResponse> workerListenerWithRelocationAndMetrics( | ||
| ActionListener<BulkByScrollResponse> potentiallyWrappedRelocationListener, | ||
|
|
@@ -413,6 +499,11 @@ static class AsyncIndexBySearchAction extends AbstractAsyncBulkByScrollAction<Re | |
| */ | ||
| private List<Thread> createdThreads = emptyList(); | ||
|
|
||
| /** | ||
| * Version of the remote cluster when reindexing from remote, or null when reindexing locally. | ||
| */ | ||
| private final Version remoteVersion; | ||
|
|
||
| AsyncIndexBySearchAction( | ||
| BulkByScrollTask task, | ||
| Logger logger, | ||
|
|
@@ -423,7 +514,8 @@ static class AsyncIndexBySearchAction extends AbstractAsyncBulkByScrollAction<Re | |
| ProjectState state, | ||
| ReindexSslConfig sslConfig, | ||
| ReindexRequest request, | ||
| ActionListener<BulkByScrollResponse> listener | ||
| ActionListener<BulkByScrollResponse> listener, | ||
| @Nullable Version remoteVersion | ||
| ) { | ||
| super( | ||
| task, | ||
|
|
@@ -444,6 +536,7 @@ static class AsyncIndexBySearchAction extends AbstractAsyncBulkByScrollAction<Re | |
| sslConfig | ||
| ); | ||
| this.destinationIndexIdMapper = destinationIndexMode(state).idFieldMapperWithoutFieldData(); | ||
| this.remoteVersion = remoteVersion; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I store it as a state variable so it can be referenced by |
||
| } | ||
|
|
||
| private IndexMode destinationIndexMode(ProjectState state) { | ||
|
|
@@ -477,7 +570,8 @@ protected PaginatedHitSource buildScrollableResultSource(BackoffPolicy backoffPo | |
| this::finishHim, | ||
| restClient, | ||
| remoteInfo, | ||
| searchRequest | ||
| searchRequest, | ||
| remoteVersion | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the case where we've enabled the PIT feature flag, but we're trying to reindex from remote from a remote node with a version < PIT was introduced, then we need to fallback to using scroll. However, since we've already done the remote version lookup, we may as well pass this value in. If this is a scrollable workflow, then |
||
| ); | ||
| } | ||
| return super.buildScrollableResultSource(backoffPolicy, searchRequest); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is called exclusively by u-b-q and d-b-q (which has no concept of remote versions since they're executed on the local node). Therefore, setting the remote version parameter to null has no effect. Subsequent changes to introduce PIT will be behind the
REINDEX_PIT_SEARCH_ENABLEDfeature flag anyways, but in the future, once that flag is lifted, this will fail the 'use pit' check, and default to scroll