|
@@ -73,8 +73,6 @@ import org.elasticsearch.transport.TransportChannel;
|
|
|
import org.elasticsearch.transport.TransportException;
|
|
|
import org.elasticsearch.transport.TransportRequest;
|
|
|
import org.elasticsearch.transport.TransportRequestOptions;
|
|
|
-import org.elasticsearch.transport.TransportResponse;
|
|
|
-import org.elasticsearch.transport.TransportResponse.Empty;
|
|
|
import org.elasticsearch.transport.TransportResponseHandler;
|
|
|
import org.elasticsearch.transport.TransportService;
|
|
|
|
|
@@ -346,17 +344,12 @@ public abstract class TransportReplicationAction<
|
|
|
} else {
|
|
|
setPhase(replicationTask, "primary");
|
|
|
|
|
|
- final ActionListener<Response> referenceClosingListener = ActionListener.wrap(response -> {
|
|
|
- primaryShardReference.close(); // release shard operation lock before responding to caller
|
|
|
- setPhase(replicationTask, "finished");
|
|
|
- onCompletionListener.onResponse(response);
|
|
|
- }, e -> handleException(primaryShardReference, e));
|
|
|
+ final ActionListener<Response> responseListener = ActionListener.wrap(response -> {
|
|
|
+ adaptResponse(response, primaryShardReference.indexShard);
|
|
|
|
|
|
- final ActionListener<Response> globalCheckpointSyncingListener = ActionListener.wrap(response -> {
|
|
|
if (syncGlobalCheckpointAfterOperation) {
|
|
|
- final IndexShard shard = primaryShardReference.indexShard;
|
|
|
try {
|
|
|
- shard.maybeSyncGlobalCheckpoint("post-operation");
|
|
|
+ primaryShardReference.indexShard.maybeSyncGlobalCheckpoint("post-operation");
|
|
|
} catch (final Exception e) {
|
|
|
// only log non-closed exceptions
|
|
|
if (ExceptionsHelper.unwrap(
|
|
@@ -364,15 +357,19 @@ public abstract class TransportReplicationAction<
|
|
|
// intentionally swallow, a missed global checkpoint sync should not fail this operation
|
|
|
logger.info(
|
|
|
new ParameterizedMessage(
|
|
|
- "{} failed to execute post-operation global checkpoint sync", shard.shardId()), e);
|
|
|
+ "{} failed to execute post-operation global checkpoint sync",
|
|
|
+ primaryShardReference.indexShard.shardId()), e);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- referenceClosingListener.onResponse(response);
|
|
|
- }, referenceClosingListener::onFailure);
|
|
|
+
|
|
|
+ primaryShardReference.close(); // release shard operation lock before responding to caller
|
|
|
+ setPhase(replicationTask, "finished");
|
|
|
+ onCompletionListener.onResponse(response);
|
|
|
+ }, e -> handleException(primaryShardReference, e));
|
|
|
|
|
|
new ReplicationOperation<>(primaryRequest.getRequest(), primaryShardReference,
|
|
|
- ActionListener.wrap(result -> result.respond(globalCheckpointSyncingListener), referenceClosingListener::onFailure),
|
|
|
+ ActionListener.map(responseListener, result -> result.finalResponseIfSuccessful),
|
|
|
newReplicasProxy(), logger, actionName, primaryRequest.getPrimaryTerm()).execute();
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
@@ -393,10 +390,19 @@ public abstract class TransportReplicationAction<
|
|
|
|
|
|
}
|
|
|
|
|
|
+ // allows subclasses to adapt the response
|
|
|
+ protected void adaptResponse(Response response, IndexShard indexShard) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ protected ActionListener<Response> wrapResponseActionListener(ActionListener<Response> listener, IndexShard shard) {
|
|
|
+ return listener;
|
|
|
+ }
|
|
|
+
|
|
|
public static class PrimaryResult<ReplicaRequest extends ReplicationRequest<ReplicaRequest>,
|
|
|
Response extends ReplicationResponse>
|
|
|
implements ReplicationOperation.PrimaryResult<ReplicaRequest> {
|
|
|
- final ReplicaRequest replicaRequest;
|
|
|
+ protected final ReplicaRequest replicaRequest;
|
|
|
public final Response finalResponseIfSuccessful;
|
|
|
public final Exception finalFailure;
|
|
|
|
|
@@ -429,11 +435,12 @@ public abstract class TransportReplicationAction<
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void respond(ActionListener<Response> listener) {
|
|
|
- if (finalResponseIfSuccessful != null) {
|
|
|
- listener.onResponse(finalResponseIfSuccessful);
|
|
|
- } else {
|
|
|
+ @Override
|
|
|
+ public void runPostReplicationActions(ActionListener<Void> listener) {
|
|
|
+ if (finalFailure != null) {
|
|
|
listener.onFailure(finalFailure);
|
|
|
+ } else {
|
|
|
+ listener.onResponse(null);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -449,11 +456,11 @@ public abstract class TransportReplicationAction<
|
|
|
this(null);
|
|
|
}
|
|
|
|
|
|
- public void respond(ActionListener<TransportResponse.Empty> listener) {
|
|
|
- if (finalFailure == null) {
|
|
|
- listener.onResponse(TransportResponse.Empty.INSTANCE);
|
|
|
- } else {
|
|
|
+ public void runPostReplicaActions(ActionListener<Void> listener) {
|
|
|
+ if (finalFailure != null) {
|
|
|
listener.onFailure(finalFailure);
|
|
|
+ } else {
|
|
|
+ listener.onResponse(null);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -503,10 +510,23 @@ public abstract class TransportReplicationAction<
|
|
|
try {
|
|
|
assert replica.getActiveOperationsCount() != 0 : "must perform shard operation under a permit";
|
|
|
final ReplicaResult replicaResult = shardOperationOnReplica(replicaRequest.getRequest(), replica);
|
|
|
- releasable.close(); // release shard operation lock before responding to caller
|
|
|
- final TransportReplicationAction.ReplicaResponse response =
|
|
|
- new ReplicaResponse(replica.getLocalCheckpoint(), replica.getLastSyncedGlobalCheckpoint());
|
|
|
- replicaResult.respond(new ResponseListener(response));
|
|
|
+ replicaResult.runPostReplicaActions(
|
|
|
+ ActionListener.wrap(r -> {
|
|
|
+ final TransportReplicationAction.ReplicaResponse response =
|
|
|
+ new ReplicaResponse(replica.getLocalCheckpoint(), replica.getLastSyncedGlobalCheckpoint());
|
|
|
+ releasable.close(); // release shard operation lock before responding to caller
|
|
|
+ if (logger.isTraceEnabled()) {
|
|
|
+ logger.trace("action [{}] completed on shard [{}] for request [{}]", transportReplicaAction,
|
|
|
+ replicaRequest.getRequest().shardId(),
|
|
|
+ replicaRequest.getRequest());
|
|
|
+ }
|
|
|
+ setPhase(task, "finished");
|
|
|
+ onCompletionListener.onResponse(response);
|
|
|
+ }, e -> {
|
|
|
+ Releasables.closeWhileHandlingException(releasable); // release shard operation lock before responding to caller
|
|
|
+ this.responseWithFailure(e);
|
|
|
+ })
|
|
|
+ );
|
|
|
} catch (final Exception e) {
|
|
|
Releasables.closeWhileHandlingException(releasable); // release shard operation lock before responding to caller
|
|
|
AsyncReplicaAction.this.onFailure(e);
|
|
@@ -564,33 +584,6 @@ public abstract class TransportReplicationAction<
|
|
|
acquireReplicaOperationPermit(replica, replicaRequest.getRequest(), this, replicaRequest.getPrimaryTerm(),
|
|
|
replicaRequest.getGlobalCheckpoint(), replicaRequest.getMaxSeqNoOfUpdatesOrDeletes());
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Listens for the response on the replica and sends the response back to the primary.
|
|
|
- */
|
|
|
- private class ResponseListener implements ActionListener<TransportResponse.Empty> {
|
|
|
- private final ReplicaResponse replicaResponse;
|
|
|
-
|
|
|
- ResponseListener(ReplicaResponse replicaResponse) {
|
|
|
- this.replicaResponse = replicaResponse;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onResponse(Empty response) {
|
|
|
- if (logger.isTraceEnabled()) {
|
|
|
- logger.trace("action [{}] completed on shard [{}] for request [{}]", transportReplicaAction,
|
|
|
- replicaRequest.getRequest().shardId(),
|
|
|
- replicaRequest.getRequest());
|
|
|
- }
|
|
|
- setPhase(task, "finished");
|
|
|
- onCompletionListener.onResponse(replicaResponse);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onFailure(Exception e) {
|
|
|
- responseWithFailure(e);
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
private IndexShard getIndexShard(final ShardId shardId) {
|