Skip to content

Commit d9b2ed6

Browse files
authored
Send clear session as routable remote request (#36805)
This commit adds a RemoteClusterAwareRequest interface that allows a request to specify which remote node it should be routed to. The remote cluster aware client will attempt to route the request directly to this node. Otherwise it will send it as a proxy action to eventually end up on the requested node. It implements the ccr clean_session action with this client.
1 parent a9834cd commit d9b2ed6

File tree

6 files changed

+114
-136
lines changed

6 files changed

+114
-136
lines changed

server/src/main/java/org/elasticsearch/transport/RemoteClusterAwareClient.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.elasticsearch.action.ActionResponse;
2626
import org.elasticsearch.client.Client;
2727
import org.elasticsearch.client.support.AbstractClient;
28+
import org.elasticsearch.cluster.node.DiscoveryNode;
2829
import org.elasticsearch.common.settings.Settings;
2930
import org.elasticsearch.threadpool.ThreadPool;
3031

@@ -45,14 +46,19 @@ final class RemoteClusterAwareClient extends AbstractClient {
4546
protected <Request extends ActionRequest, Response extends ActionResponse>
4647
void doExecute(Action<Response> action, Request request, ActionListener<Response> listener) {
4748
remoteClusterService.ensureConnected(clusterAlias, ActionListener.wrap(res -> {
48-
Transport.Connection connection = remoteClusterService.getConnection(clusterAlias);
49+
Transport.Connection connection;
50+
if (request instanceof RemoteClusterAwareRequest) {
51+
DiscoveryNode preferredTargetNode = ((RemoteClusterAwareRequest) request).getPreferredTargetNode();
52+
connection = remoteClusterService.getConnection(preferredTargetNode, clusterAlias);
53+
} else {
54+
connection = remoteClusterService.getConnection(clusterAlias);
55+
}
4956
service.sendRequest(connection, action.name(), request, TransportRequestOptions.EMPTY,
5057
new ActionListenerResponseHandler<>(listener, action.getResponseReader()));
5158
},
5259
listener::onFailure));
5360
}
5461

55-
5662
@Override
5763
public void close() {
5864
// do nothing
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.transport;
21+
22+
import org.elasticsearch.cluster.node.DiscoveryNode;
23+
24+
public interface RemoteClusterAwareRequest {
25+
26+
/**
27+
* Returns the preferred discovery node for this request. The remote cluster client will attempt to send
28+
* this request directly to this node. Otherwise, it will send the request as a proxy action that will
29+
* be routed by the remote cluster to this node.
30+
*
31+
* @return preferred discovery node
32+
*/
33+
DiscoveryNode getPreferredTargetNode();
34+
35+
}

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/repositories/ClearCcrRestoreSessionAction.java

Lines changed: 30 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,19 @@
77
package org.elasticsearch.xpack.ccr.action.repositories;
88

99
import org.elasticsearch.action.Action;
10-
import org.elasticsearch.action.FailedNodeException;
10+
import org.elasticsearch.action.ActionListener;
11+
import org.elasticsearch.action.ActionResponse;
1112
import org.elasticsearch.action.support.ActionFilters;
12-
import org.elasticsearch.action.support.nodes.BaseNodeResponse;
13-
import org.elasticsearch.action.support.nodes.BaseNodesResponse;
14-
import org.elasticsearch.action.support.nodes.TransportNodesAction;
15-
import org.elasticsearch.cluster.ClusterName;
16-
import org.elasticsearch.cluster.node.DiscoveryNode;
17-
import org.elasticsearch.cluster.service.ClusterService;
13+
import org.elasticsearch.action.support.HandledTransportAction;
1814
import org.elasticsearch.common.inject.Inject;
1915
import org.elasticsearch.common.io.stream.StreamInput;
20-
import org.elasticsearch.common.io.stream.StreamOutput;
16+
import org.elasticsearch.common.io.stream.Writeable;
17+
import org.elasticsearch.tasks.Task;
2118
import org.elasticsearch.threadpool.ThreadPool;
19+
import org.elasticsearch.transport.TransportActionProxy;
2220
import org.elasticsearch.transport.TransportService;
2321
import org.elasticsearch.xpack.ccr.repository.CcrRestoreSourceService;
2422

25-
import java.io.IOException;
26-
import java.util.List;
27-
2823
public class ClearCcrRestoreSessionAction extends Action<ClearCcrRestoreSessionAction.ClearCcrRestoreSessionResponse> {
2924

3025
public static final ClearCcrRestoreSessionAction INSTANCE = new ClearCcrRestoreSessionAction();
@@ -36,86 +31,47 @@ private ClearCcrRestoreSessionAction() {
3631

3732
@Override
3833
public ClearCcrRestoreSessionResponse newResponse() {
39-
return new ClearCcrRestoreSessionResponse();
34+
throw new UnsupportedOperationException();
4035
}
4136

42-
public static class TransportDeleteCcrRestoreSessionAction extends TransportNodesAction<ClearCcrRestoreSessionRequest,
43-
ClearCcrRestoreSessionResponse, ClearCcrRestoreSessionRequest.Request, Response> {
37+
@Override
38+
public Writeable.Reader<ClearCcrRestoreSessionResponse> getResponseReader() {
39+
return ClearCcrRestoreSessionResponse::new;
40+
}
41+
42+
public static class TransportDeleteCcrRestoreSessionAction
43+
extends HandledTransportAction<ClearCcrRestoreSessionRequest, ClearCcrRestoreSessionResponse> {
4444

4545
private final CcrRestoreSourceService ccrRestoreService;
46+
private final ThreadPool threadPool;
4647

4748
@Inject
48-
public TransportDeleteCcrRestoreSessionAction(ThreadPool threadPool, ClusterService clusterService, ActionFilters actionFilters,
49-
TransportService transportService, CcrRestoreSourceService ccrRestoreService) {
50-
super(NAME, threadPool, clusterService, transportService, actionFilters, ClearCcrRestoreSessionRequest::new,
51-
ClearCcrRestoreSessionRequest.Request::new, ThreadPool.Names.GENERIC, Response.class);
49+
public TransportDeleteCcrRestoreSessionAction(ActionFilters actionFilters, TransportService transportService,
50+
CcrRestoreSourceService ccrRestoreService) {
51+
super(NAME, transportService, actionFilters, ClearCcrRestoreSessionRequest::new);
52+
TransportActionProxy.registerProxyAction(transportService, NAME, ClearCcrRestoreSessionResponse::new);
5253
this.ccrRestoreService = ccrRestoreService;
54+
this.threadPool = transportService.getThreadPool();
5355
}
5456

5557
@Override
56-
protected ClearCcrRestoreSessionResponse newResponse(ClearCcrRestoreSessionRequest request, List<Response> responses,
57-
List<FailedNodeException> failures) {
58-
return new ClearCcrRestoreSessionResponse(clusterService.getClusterName(), responses, failures);
59-
}
60-
61-
@Override
62-
protected ClearCcrRestoreSessionRequest.Request newNodeRequest(String nodeId, ClearCcrRestoreSessionRequest request) {
63-
return request.getRequest();
64-
}
65-
66-
@Override
67-
protected Response newNodeResponse() {
68-
return new Response();
69-
}
70-
71-
@Override
72-
protected Response nodeOperation(ClearCcrRestoreSessionRequest.Request request) {
73-
ccrRestoreService.closeSession(request.getSessionUUID());
74-
return new Response(clusterService.localNode());
58+
protected void doExecute(Task task, ClearCcrRestoreSessionRequest request,
59+
ActionListener<ClearCcrRestoreSessionResponse> listener) {
60+
// TODO: Currently blocking actions might occur in the session closed callbacks. This dispatch
61+
// may be unnecessary when we remove these callbacks.
62+
threadPool.generic().execute(() -> {
63+
ccrRestoreService.closeSession(request.getSessionUUID());
64+
listener.onResponse(new ClearCcrRestoreSessionResponse());
65+
});
7566
}
7667
}
7768

78-
public static class Response extends BaseNodeResponse {
79-
80-
private Response() {
81-
}
82-
83-
private Response(StreamInput in) throws IOException {
84-
readFrom(in);
85-
}
86-
87-
private Response(DiscoveryNode node) {
88-
super(node);
89-
}
90-
91-
@Override
92-
public void writeTo(StreamOutput out) throws IOException {
93-
super.writeTo(out);
94-
}
95-
96-
@Override
97-
public void readFrom(StreamInput in) throws IOException {
98-
super.readFrom(in);
99-
}
100-
}
101-
102-
public static class ClearCcrRestoreSessionResponse extends BaseNodesResponse<Response> {
69+
public static class ClearCcrRestoreSessionResponse extends ActionResponse {
10370

10471
ClearCcrRestoreSessionResponse() {
10572
}
10673

107-
ClearCcrRestoreSessionResponse(ClusterName clusterName, List<Response> chunkResponses, List<FailedNodeException> failures) {
108-
super(clusterName, chunkResponses, failures);
109-
}
110-
111-
@Override
112-
protected List<Response> readNodesFrom(StreamInput in) throws IOException {
113-
return in.readList(Response::new);
114-
}
115-
116-
@Override
117-
protected void writeNodesTo(StreamOutput out, List<Response> nodes) throws IOException {
118-
out.writeList(nodes);
74+
ClearCcrRestoreSessionResponse(StreamInput in) {
11975
}
12076
}
12177
}

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/repositories/ClearCcrRestoreSessionRequest.java

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,52 @@
66

77
package org.elasticsearch.xpack.ccr.action.repositories;
88

9-
import org.elasticsearch.action.support.nodes.BaseNodeRequest;
10-
import org.elasticsearch.action.support.nodes.BaseNodesRequest;
9+
import org.elasticsearch.action.ActionRequest;
10+
import org.elasticsearch.action.ActionRequestValidationException;
11+
import org.elasticsearch.transport.RemoteClusterAwareRequest;
12+
import org.elasticsearch.cluster.node.DiscoveryNode;
1113
import org.elasticsearch.common.io.stream.StreamInput;
1214
import org.elasticsearch.common.io.stream.StreamOutput;
1315

1416
import java.io.IOException;
1517

16-
public class ClearCcrRestoreSessionRequest extends BaseNodesRequest<ClearCcrRestoreSessionRequest> {
18+
public class ClearCcrRestoreSessionRequest extends ActionRequest implements RemoteClusterAwareRequest {
1719

18-
private Request request;
20+
private DiscoveryNode node;
21+
private String sessionUUID;
1922

20-
ClearCcrRestoreSessionRequest() {
23+
ClearCcrRestoreSessionRequest(StreamInput in) throws IOException {
24+
super.readFrom(in);
25+
sessionUUID = in.readString();
2126
}
2227

23-
public ClearCcrRestoreSessionRequest(String nodeId, Request request) {
24-
super(nodeId);
25-
this.request = request;
28+
public ClearCcrRestoreSessionRequest(String sessionUUID, DiscoveryNode node) {
29+
this.sessionUUID = sessionUUID;
30+
this.node = node;
2631
}
2732

2833
@Override
29-
public void readFrom(StreamInput streamInput) throws IOException {
30-
super.readFrom(streamInput);
31-
request = new Request();
32-
request.readFrom(streamInput);
34+
public ActionRequestValidationException validate() {
35+
return null;
3336
}
3437

3538
@Override
36-
public void writeTo(StreamOutput streamOutput) throws IOException {
37-
super.writeTo(streamOutput);
38-
request.writeTo(streamOutput);
39+
public void readFrom(StreamInput in) throws IOException {
40+
throw new UnsupportedOperationException();
3941
}
4042

41-
public Request getRequest() {
42-
return request;
43+
@Override
44+
public void writeTo(StreamOutput out) throws IOException {
45+
super.writeTo(out);
46+
out.writeString(sessionUUID);
4347
}
4448

45-
public static class Request extends BaseNodeRequest {
46-
47-
private String sessionUUID;
48-
49-
Request() {
50-
}
51-
52-
public Request(String nodeId, String sessionUUID) {
53-
super(nodeId);
54-
this.sessionUUID = sessionUUID;
55-
}
56-
57-
@Override
58-
public void readFrom(StreamInput in) throws IOException {
59-
super.readFrom(in);
60-
sessionUUID = in.readString();
61-
}
62-
63-
@Override
64-
public void writeTo(StreamOutput out) throws IOException {
65-
super.writeTo(out);
66-
out.writeString(sessionUUID);
67-
}
49+
String getSessionUUID() {
50+
return sessionUUID;
51+
}
6852

69-
public String getSessionUUID() {
70-
return sessionUUID;
71-
}
53+
@Override
54+
public DiscoveryNode getPreferredTargetNode() {
55+
return node;
7256
}
7357
}

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/repositories/PutCcrRestoreSessionAction.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.action.support.single.shard.TransportSingleShardAction;
1313
import org.elasticsearch.cluster.ClusterState;
1414
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
15+
import org.elasticsearch.cluster.node.DiscoveryNode;
1516
import org.elasticsearch.cluster.routing.ShardsIterator;
1617
import org.elasticsearch.cluster.service.ClusterService;
1718
import org.elasticsearch.common.inject.Inject;
@@ -70,7 +71,7 @@ protected PutCcrRestoreSessionResponse shardOperation(PutCcrRestoreSessionReques
7071
throw new ShardNotFoundException(shardId);
7172
}
7273
ccrRestoreService.openSession(request.getSessionUUID(), indexShard);
73-
return new PutCcrRestoreSessionResponse(indexShard.routingEntry().currentNodeId());
74+
return new PutCcrRestoreSessionResponse(clusterService.localNode());
7475
}
7576

7677
@Override
@@ -93,34 +94,34 @@ protected ShardsIterator shards(ClusterState state, InternalRequest request) {
9394

9495
public static class PutCcrRestoreSessionResponse extends ActionResponse {
9596

96-
private String nodeId;
97+
private DiscoveryNode node;
9798

9899
PutCcrRestoreSessionResponse() {
99100
}
100101

101-
PutCcrRestoreSessionResponse(String nodeId) {
102-
this.nodeId = nodeId;
102+
PutCcrRestoreSessionResponse(DiscoveryNode node) {
103+
this.node = node;
103104
}
104105

105106
PutCcrRestoreSessionResponse(StreamInput in) throws IOException {
106107
super(in);
107-
nodeId = in.readString();
108+
node = new DiscoveryNode(in);
108109
}
109110

110111
@Override
111112
public void readFrom(StreamInput in) throws IOException {
112113
super.readFrom(in);
113-
nodeId = in.readString();
114+
node = new DiscoveryNode(in);
114115
}
115116

116117
@Override
117118
public void writeTo(StreamOutput out) throws IOException {
118119
super.writeTo(out);
119-
out.writeString(nodeId);
120+
node.writeTo(out);
120121
}
121122

122-
public String getNodeId() {
123-
return nodeId;
123+
public DiscoveryNode getNode() {
124+
return node;
124125
}
125126
}
126127
}

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/repository/CcrRepository.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ public void restoreShard(IndexShard indexShard, SnapshotId snapshotId, Version v
253253
String sessionUUID = UUIDs.randomBase64UUID();
254254
PutCcrRestoreSessionAction.PutCcrRestoreSessionResponse response = remoteClient.execute(PutCcrRestoreSessionAction.INSTANCE,
255255
new PutCcrRestoreSessionRequest(sessionUUID, leaderShardId, recoveryMetadata)).actionGet();
256-
String nodeId = response.getNodeId();
256+
DiscoveryNode node = response.getNode();
257257
// TODO: Implement file restore
258-
closeSession(remoteClient, nodeId, sessionUUID);
258+
closeSession(remoteClient, node, sessionUUID);
259259
maybeUpdateMappings(client, remoteClient, leaderIndex, indexShard.indexSettings());
260260
}
261261

@@ -278,13 +278,9 @@ private void maybeUpdateMappings(Client localClient, Client remoteClient, Index
278278
}
279279
}
280280

281-
private void closeSession(Client remoteClient, String nodeId, String sessionUUID) {
282-
ClearCcrRestoreSessionRequest clearRequest = new ClearCcrRestoreSessionRequest(nodeId,
283-
new ClearCcrRestoreSessionRequest.Request(nodeId, sessionUUID));
281+
private void closeSession(Client remoteClient, DiscoveryNode node, String sessionUUID) {
282+
ClearCcrRestoreSessionRequest clearRequest = new ClearCcrRestoreSessionRequest(sessionUUID, node);
284283
ClearCcrRestoreSessionAction.ClearCcrRestoreSessionResponse response =
285284
remoteClient.execute(ClearCcrRestoreSessionAction.INSTANCE, clearRequest).actionGet();
286-
if (response.hasFailures()) {
287-
throw response.failures().get(0);
288-
}
289285
}
290286
}

0 commit comments

Comments
 (0)