Bulk API: Properly retry execution on temporal state changes, closes #1343.
This commit is contained in:
parent
0977b793da
commit
305cf4a567
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.bulk;
|
package org.elasticsearch.action.bulk;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticSearchException;
|
||||||
import org.elasticsearch.ExceptionsHelper;
|
import org.elasticsearch.ExceptionsHelper;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.RoutingMissingException;
|
import org.elasticsearch.action.RoutingMissingException;
|
||||||
|
@ -158,6 +159,10 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation
|
||||||
responses[i] = new BulkItemResponse(item.id(), indexRequest.opType().toString().toLowerCase(),
|
responses[i] = new BulkItemResponse(item.id(), indexRequest.opType().toString().toLowerCase(),
|
||||||
new IndexResponse(indexRequest.index(), indexRequest.type(), indexRequest.id(), version));
|
new IndexResponse(indexRequest.index(), indexRequest.type(), indexRequest.id(), version));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// rethrow the failure if we are going to retry on primary and let parent failure to handle it
|
||||||
|
if (retryPrimaryException(e)) {
|
||||||
|
throw (ElasticSearchException) e;
|
||||||
|
}
|
||||||
logger.debug("[{}][{}] failed to bulk item (index) {}", e, shardRequest.request.index(), shardRequest.shardId, indexRequest);
|
logger.debug("[{}][{}] failed to bulk item (index) {}", e, shardRequest.request.index(), shardRequest.shardId, indexRequest);
|
||||||
responses[i] = new BulkItemResponse(item.id(), indexRequest.opType().toString().toLowerCase(),
|
responses[i] = new BulkItemResponse(item.id(), indexRequest.opType().toString().toLowerCase(),
|
||||||
new BulkItemResponse.Failure(indexRequest.index(), indexRequest.type(), indexRequest.id(), ExceptionsHelper.detailedMessage(e)));
|
new BulkItemResponse.Failure(indexRequest.index(), indexRequest.type(), indexRequest.id(), ExceptionsHelper.detailedMessage(e)));
|
||||||
|
@ -174,6 +179,10 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation
|
||||||
responses[i] = new BulkItemResponse(item.id(), "delete",
|
responses[i] = new BulkItemResponse(item.id(), "delete",
|
||||||
new DeleteResponse(deleteRequest.index(), deleteRequest.type(), deleteRequest.id(), delete.version(), delete.notFound()));
|
new DeleteResponse(deleteRequest.index(), deleteRequest.type(), deleteRequest.id(), delete.version(), delete.notFound()));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// rethrow the failure if we are going to retry on primary and let parent failure to handle it
|
||||||
|
if (retryPrimaryException(e)) {
|
||||||
|
throw (ElasticSearchException) e;
|
||||||
|
}
|
||||||
logger.debug("[{}][{}] failed to bulk item (delete) {}", e, shardRequest.request.index(), shardRequest.shardId, deleteRequest);
|
logger.debug("[{}][{}] failed to bulk item (delete) {}", e, shardRequest.request.index(), shardRequest.shardId, deleteRequest);
|
||||||
responses[i] = new BulkItemResponse(item.id(), "delete",
|
responses[i] = new BulkItemResponse(item.id(), "delete",
|
||||||
new BulkItemResponse.Failure(deleteRequest.index(), deleteRequest.type(), deleteRequest.id(), ExceptionsHelper.detailedMessage(e)));
|
new BulkItemResponse.Failure(deleteRequest.index(), deleteRequest.type(), deleteRequest.id(), ExceptionsHelper.detailedMessage(e)));
|
||||||
|
|
|
@ -160,6 +160,42 @@ public abstract class TransportShardReplicationOperationAction<Request extends S
|
||||||
return indicesService.indexServiceSafe(shardRequest.request.index()).shardSafe(shardRequest.shardId);
|
return indicesService.indexServiceSafe(shardRequest.request.index()).shardSafe(shardRequest.shardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean retryPrimaryException(Throwable e) {
|
||||||
|
Throwable cause = ExceptionsHelper.unwrapCause(e);
|
||||||
|
return cause instanceof IndexShardMissingException ||
|
||||||
|
cause instanceof IllegalIndexShardStateException ||
|
||||||
|
cause instanceof IndexMissingException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should an exception be ignored when the operation is performed on the replica.
|
||||||
|
*/
|
||||||
|
boolean ignoreReplicaException(Throwable e) {
|
||||||
|
Throwable cause = ExceptionsHelper.unwrapCause(e);
|
||||||
|
if (cause instanceof IllegalIndexShardStateException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cause instanceof IndexMissingException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cause instanceof IndexShardMissingException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cause instanceof ConnectTransportException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// on version conflict or document missing, it means
|
||||||
|
// that a news change has crept into the replica, and its fine
|
||||||
|
if (cause instanceof VersionConflictEngineException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// same here
|
||||||
|
if (cause instanceof DocumentAlreadyExistsEngineException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class OperationTransportHandler extends BaseTransportRequestHandler<Request> {
|
class OperationTransportHandler extends BaseTransportRequestHandler<Request> {
|
||||||
|
|
||||||
@Override public Request newInstance() {
|
@Override public Request newInstance() {
|
||||||
|
@ -429,7 +465,7 @@ public abstract class TransportShardReplicationOperationAction<Request extends S
|
||||||
performReplicas(response);
|
performReplicas(response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// shard has not been allocated yet, retry it here
|
// shard has not been allocated yet, retry it here
|
||||||
if (e instanceof IndexShardMissingException || e instanceof IllegalIndexShardStateException || e instanceof IndexMissingException) {
|
if (retryPrimaryException(e)) {
|
||||||
retry(fromDiscoveryListener, shard.shardId());
|
retry(fromDiscoveryListener, shard.shardId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -572,35 +608,6 @@ public abstract class TransportShardReplicationOperationAction<Request extends S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Should an exception be ignored when the operation is performed on the replica.
|
|
||||||
*/
|
|
||||||
boolean ignoreReplicaException(Throwable e) {
|
|
||||||
Throwable cause = ExceptionsHelper.unwrapCause(e);
|
|
||||||
if (cause instanceof IllegalIndexShardStateException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (cause instanceof IndexMissingException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (cause instanceof IndexShardMissingException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (cause instanceof ConnectTransportException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// on version conflict or document missing, it means
|
|
||||||
// that a news change has crept into the replica, and its fine
|
|
||||||
if (cause instanceof VersionConflictEngineException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// same here
|
|
||||||
if (cause instanceof DocumentAlreadyExistsEngineException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PrimaryResponse<T> {
|
public static class PrimaryResponse<T> {
|
||||||
|
|
Loading…
Reference in New Issue