All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.update.processor.TolerantUpdateProcessorFactory Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.solr.update.processor;

import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.update.processor.DistributedUpdateProcessor.DistribPhase;
import org.apache.solr.util.plugin.SolrCoreAware;

import static org.apache.solr.update.processor.DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM;

/**
 * 

* Suppresses errors for individual add/delete commands within a single request. * Instead of failing on the first error, at most maxErrors errors (or unlimited * if -1==maxErrors) are logged and recorded the batch continues. * The client will receive a status==200 response, which includes a list of errors * that were tolerated. *

*

* If more then maxErrors occur, the first exception recorded will be re-thrown, * Solr will respond with status==5xx or status==4xx * (depending on the underlying exceptions) and it won't finish processing any more updates in the request. * (ie: subsequent update commands in the request will not be processed even if they are valid). *

* *

* maxErrors is an int value that can be specified in the configuration and/or overridden * per request. If unset, it will default to {@link Integer#MAX_VALUE}. Specifying an explicit value * of -1 is supported as shorthand for {@link Integer#MAX_VALUE}, all other negative * integer values are not supported. *

*

* An example configuration would be: *

*
 * <updateRequestProcessorChain name="tolerant-chain">
 *   <processor class="solr.TolerantUpdateProcessorFactory">
 *     <int name="maxErrors">10</int>
 *   </processor>
 *   <processor class="solr.RunUpdateProcessorFactory" />
 * </updateRequestProcessorChain>
 * 
 * 
* *

* The maxErrors parameter in the above chain could be overwritten per request, for example: *

*
 * curl http://localhost:8983/update?update.chain=tolerant-chain&maxErrors=100 -H "Content-Type: text/xml" -d @myfile.xml
 * 
* *

* NOTE: The behavior of this UpdateProcessofFactory in conjunction with indexing operations * while a Shard Split is actively in progress is not well defined (or sufficiently tested). Users * of this update processor are encouraged to either disable it, or pause updates, while any shard * splitting is in progress (see SOLR-8881 * for more details.) *

* @since 6.1.0 */ public class TolerantUpdateProcessorFactory extends UpdateRequestProcessorFactory implements SolrCoreAware, UpdateRequestProcessorFactory.RunAlways { /** * Parameter that defines how many errors the UpdateRequestProcessor will tolerate */ private final static String MAX_ERRORS_PARAM = "maxErrors"; /** * Default maxErrors value that will be use if the value is not set in configuration * or in the request */ private int defaultMaxErrors = Integer.MAX_VALUE; private boolean informed = false; @SuppressWarnings("rawtypes") @Override public void init( NamedList args ) { Object maxErrorsObj = args.get(MAX_ERRORS_PARAM); if (maxErrorsObj != null) { try { defaultMaxErrors = Integer.parseInt(maxErrorsObj.toString()); } catch (Exception e) { throw new SolrException(ErrorCode.SERVER_ERROR, "Unnable to parse maxErrors parameter: " + maxErrorsObj, e); } if (defaultMaxErrors < -1) { throw new SolrException(ErrorCode.SERVER_ERROR, "Config option '"+MAX_ERRORS_PARAM + "' must either be non-negative, or -1 to indicate 'unlimiited': " + maxErrorsObj.toString()); } } } @Override public void inform(SolrCore core) { informed = true; if (null == core.getLatestSchema().getUniqueKeyField()) { throw new SolrException(ErrorCode.SERVER_ERROR, this.getClass().getName() + " requires a schema that includes a uniqueKey field."); } } @Override public UpdateRequestProcessor getInstance(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next) { assert informed : "inform(SolrCore) never called?"; // short circut if we're a replica processing commands from our leader DistribPhase distribPhase = DistribPhase.parseParam(req.getParams().get(DISTRIB_UPDATE_PARAM)); if (DistribPhase.FROMLEADER.equals(distribPhase)) { return next; } DistributedUpdateProcessorFactory.addParamToDistributedRequestWhitelist(req, MAX_ERRORS_PARAM); int maxErrors = req.getParams().getInt(MAX_ERRORS_PARAM, defaultMaxErrors); if (maxErrors < -1) { throw new SolrException(ErrorCode.BAD_REQUEST, "'"+MAX_ERRORS_PARAM + "' must either be non-negative, or -1 to indicate 'unlimiited': " + maxErrors); } // NOTE: even if 0==maxErrors, we still inject processor into chain so responses has expected header info return new TolerantUpdateProcessor(req, rsp, next, maxErrors, distribPhase); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy