4444import org .elasticsearch .common .inject .Inject ;
4545import org .elasticsearch .common .settings .Settings ;
4646import org .elasticsearch .index .engine .Engine ;
47+ import org .elasticsearch .index .mapper .MapperParsingException ;
4748import org .elasticsearch .index .mapper .Mapping ;
4849import org .elasticsearch .index .mapper .SourceToParse ;
4950import org .elasticsearch .index .shard .IndexShard ;
5051import org .elasticsearch .index .shard .ShardId ;
51- import org .elasticsearch .index .translog .Translog .Location ;
5252import org .elasticsearch .indices .IndicesService ;
5353import org .elasticsearch .ingest .IngestService ;
5454import org .elasticsearch .tasks .Task ;
6565 * <li><b>allowIdGeneration</b>: If the id is set not, should it be generated. Defaults to <tt>true</tt>.
6666 * </ul>
6767 */
68- public class TransportIndexAction extends TransportWriteAction <IndexRequest , IndexResponse > {
68+ public class TransportIndexAction extends TransportWriteAction <IndexRequest , IndexRequest , IndexResponse > {
6969
7070 private final AutoCreateIndex autoCreateIndex ;
7171 private final boolean allowIdGeneration ;
@@ -83,7 +83,7 @@ public TransportIndexAction(Settings settings, TransportService transportService
8383 MappingUpdatedAction mappingUpdatedAction , ActionFilters actionFilters ,
8484 IndexNameExpressionResolver indexNameExpressionResolver , AutoCreateIndex autoCreateIndex ) {
8585 super (settings , IndexAction .NAME , transportService , clusterService , indicesService , threadPool , shardStateAction ,
86- actionFilters , indexNameExpressionResolver , IndexRequest ::new , ThreadPool .Names .INDEX );
86+ actionFilters , indexNameExpressionResolver , IndexRequest ::new , IndexRequest :: new , ThreadPool .Names .INDEX );
8787 this .mappingUpdatedAction = mappingUpdatedAction ;
8888 this .createIndexAction = createIndexAction ;
8989 this .autoCreateIndex = autoCreateIndex ;
@@ -162,65 +162,88 @@ protected IndexResponse newResponseInstance() {
162162 }
163163
164164 @ Override
165- protected WriteResult <IndexResponse > onPrimaryShard (IndexRequest request , IndexShard indexShard ) throws Exception {
166- return executeIndexRequestOnPrimary (request , indexShard , mappingUpdatedAction );
165+ protected WritePrimaryResult shardOperationOnPrimary (IndexRequest request , IndexShard primary ) throws Exception {
166+ final Engine .IndexResult indexResult = executeIndexRequestOnPrimary (request , primary , mappingUpdatedAction );
167+ final IndexResponse response = indexResult .hasFailure () ? null :
168+ new IndexResponse (primary .shardId (), request .type (), request .id (), indexResult .getVersion (),
169+ indexResult .isCreated ());
170+ return new WritePrimaryResult (request , response , indexResult .getTranslogLocation (), indexResult .getFailure (), primary );
167171 }
168172
169173 @ Override
170- protected Location onReplicaShard (IndexRequest request , IndexShard indexShard ) {
171- return executeIndexRequestOnReplica (request , indexShard ).getTranslogLocation ();
174+ protected WriteReplicaResult shardOperationOnReplica (IndexRequest request , IndexShard replica ) throws Exception {
175+ final Engine .IndexResult indexResult = executeIndexRequestOnReplica (request , replica );
176+ return new WriteReplicaResult (request , indexResult .getTranslogLocation (), indexResult .getFailure (), replica );
172177 }
173178
174179 /**
175180 * Execute the given {@link IndexRequest} on a replica shard, throwing a
176181 * {@link RetryOnReplicaException} if the operation needs to be re-tried.
177182 */
178- public static Engine .Index executeIndexRequestOnReplica (IndexRequest request , IndexShard indexShard ) {
179- final ShardId shardId = indexShard .shardId ();
183+ public static Engine .IndexResult executeIndexRequestOnReplica (IndexRequest request , IndexShard replica ) {
184+ final ShardId shardId = replica .shardId ();
180185 SourceToParse sourceToParse = SourceToParse .source (SourceToParse .Origin .REPLICA , shardId .getIndexName (), request .type (), request .id (), request .source ())
181186 .routing (request .routing ()).parent (request .parent ()).timestamp (request .timestamp ()).ttl (request .ttl ());
182187
183- final Engine .Index operation = indexShard .prepareIndexOnReplica (sourceToParse , request .version (), request .versionType (), request .getAutoGeneratedTimestamp (), request .isRetry ());
188+ final Engine .Index operation ;
189+ try {
190+ operation = replica .prepareIndexOnReplica (sourceToParse , request .version (), request .versionType (), request .getAutoGeneratedTimestamp (), request .isRetry ());
191+ } catch (MapperParsingException e ) {
192+ return new Engine .IndexResult (e , request .version ());
193+ }
184194 Mapping update = operation .parsedDoc ().dynamicMappingsUpdate ();
185195 if (update != null ) {
186196 throw new RetryOnReplicaException (shardId , "Mappings are not available on the replica yet, triggered update: " + update );
187197 }
188- indexShard .index (operation );
189- return operation ;
198+ return replica .index (operation );
190199 }
191200
192201 /** Utility method to prepare an index operation on primary shards */
193- public static Engine .Index prepareIndexOperationOnPrimary (IndexRequest request , IndexShard indexShard ) {
202+ static Engine .Index prepareIndexOperationOnPrimary (IndexRequest request , IndexShard primary ) {
194203 SourceToParse sourceToParse = SourceToParse .source (SourceToParse .Origin .PRIMARY , request .index (), request .type (), request .id (), request .source ())
195204 .routing (request .routing ()).parent (request .parent ()).timestamp (request .timestamp ()).ttl (request .ttl ());
196- return indexShard .prepareIndexOnPrimary (sourceToParse , request .version (), request .versionType (), request .getAutoGeneratedTimestamp (), request .isRetry ());
205+ return primary .prepareIndexOnPrimary (sourceToParse , request .version (), request .versionType (), request .getAutoGeneratedTimestamp (), request .isRetry ());
197206 }
198207
199- public static WriteResult < IndexResponse > executeIndexRequestOnPrimary (IndexRequest request , IndexShard indexShard ,
208+ public static Engine . IndexResult executeIndexRequestOnPrimary (IndexRequest request , IndexShard primary ,
200209 MappingUpdatedAction mappingUpdatedAction ) throws Exception {
201- Engine .Index operation = prepareIndexOperationOnPrimary (request , indexShard );
210+ Engine .Index operation ;
211+ try {
212+ operation = prepareIndexOperationOnPrimary (request , primary );
213+ } catch (MapperParsingException | IllegalArgumentException e ) {
214+ return new Engine .IndexResult (e , request .version ());
215+ }
202216 Mapping update = operation .parsedDoc ().dynamicMappingsUpdate ();
203- final ShardId shardId = indexShard .shardId ();
217+ final ShardId shardId = primary .shardId ();
204218 if (update != null ) {
205- mappingUpdatedAction .updateMappingOnMaster (shardId .getIndex (), request .type (), update );
206- operation = prepareIndexOperationOnPrimary (request , indexShard );
219+ // can throw timeout exception when updating mappings or ISE for attempting to update default mappings
220+ // which are bubbled up
221+ try {
222+ mappingUpdatedAction .updateMappingOnMaster (shardId .getIndex (), request .type (), update );
223+ } catch (IllegalArgumentException e ) {
224+ // throws IAE on conflicts merging dynamic mappings
225+ return new Engine .IndexResult (e , request .version ());
226+ }
227+ try {
228+ operation = prepareIndexOperationOnPrimary (request , primary );
229+ } catch (MapperParsingException | IllegalArgumentException e ) {
230+ return new Engine .IndexResult (e , request .version ());
231+ }
207232 update = operation .parsedDoc ().dynamicMappingsUpdate ();
208233 if (update != null ) {
209234 throw new ReplicationOperation .RetryOnPrimaryException (shardId ,
210235 "Dynamic mappings are not available on the node that holds the primary yet" );
211236 }
212237 }
213- indexShard .index (operation );
214-
215- // update the version on request so it will happen on the replicas
216- final long version = operation .version ();
217- request .version (version );
218- request .versionType (request .versionType ().versionTypeForReplicationAndRecovery ());
219-
220- assert request .versionType ().validateVersionForWrites (request .version ());
221-
222- IndexResponse response = new IndexResponse (shardId , request .type (), request .id (), request .version (), operation .isCreated ());
223- return new WriteResult <>(response , operation .getTranslogLocation ());
238+ Engine .IndexResult result = primary .index (operation );
239+ if (result .hasFailure () == false ) {
240+ // update the version on request so it will happen on the replicas
241+ final long version = result .getVersion ();
242+ request .version (version );
243+ request .versionType (request .versionType ().versionTypeForReplicationAndRecovery ());
244+ assert request .versionType ().validateVersionForWrites (request .version ());
245+ }
246+ return result ;
224247 }
225248
226249 private void processIngestIndexRequest (Task task , IndexRequest indexRequest , ActionListener listener ) {
0 commit comments