mirror of https://github.com/apache/lucene.git
SOLR-6761: Ability to ignore commit and optimize requests from clients when running in SolrCloud mode.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1648775 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
16f17fa81d
commit
93e19a3148
|
@ -268,6 +268,9 @@ New Features
|
|||
|
||||
* SOLR-6435: Add bin/post script to simplify posting content to Solr (ehatcher)
|
||||
|
||||
* SOLR-6761: Ability to ignore commit and/or optimize requests from clients when running in
|
||||
SolrCloud mode using the IgnoreCommitOptimizeUpdateProcessorFactory. (Timothy Potter)
|
||||
|
||||
|
||||
Bug Fixes
|
||||
----------------------
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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 static org.apache.solr.common.SolrException.ErrorCode;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.params.SolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.update.CommitUpdateCommand;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Gives system administrators a way to ignore explicit commit or optimize requests from clients.
|
||||
* The factory can be configured to return a specific HTTP response code, default is 403, and
|
||||
* optional response message, such as to warn the client application that its request was ignored.
|
||||
* </p>
|
||||
*/
|
||||
public class IgnoreCommitOptimizeUpdateProcessorFactory extends UpdateRequestProcessorFactory {
|
||||
|
||||
public final static Logger log = LoggerFactory.getLogger(IgnoreCommitOptimizeUpdateProcessorFactory.class);
|
||||
|
||||
private static final String DEFAULT_RESPONSE_MSG = "Explicit commit/optimize requests are forbidden!";
|
||||
|
||||
protected ErrorCode errorCode;
|
||||
protected String responseMsg;
|
||||
protected boolean ignoreOptimizeOnly = false; // default behavior is to ignore commits and optimize
|
||||
|
||||
@Override
|
||||
public void init(final NamedList args) {
|
||||
SolrParams params = (args != null) ? SolrParams.toSolrParams(args) : null;
|
||||
if (params == null) {
|
||||
errorCode = ErrorCode.FORBIDDEN; // default is 403 error
|
||||
responseMsg = DEFAULT_RESPONSE_MSG;
|
||||
ignoreOptimizeOnly = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ignoreOptimizeOnly = params.getBool("ignoreOptimizeOnly", false);
|
||||
|
||||
int statusCode = params.getInt("statusCode", ErrorCode.FORBIDDEN.code);
|
||||
if (statusCode == 200) {
|
||||
errorCode = null; // not needed but makes the logic clearer
|
||||
responseMsg = params.get("responseMessage"); // OK to be null for 200's
|
||||
} else {
|
||||
errorCode = ErrorCode.getErrorCode(statusCode);
|
||||
if (errorCode == ErrorCode.UNKNOWN) {
|
||||
// only allow the error codes supported by the SolrException.ErrorCode class
|
||||
StringBuilder validCodes = new StringBuilder();
|
||||
int appended = 0;
|
||||
for (ErrorCode code : ErrorCode.values()) {
|
||||
if (code != ErrorCode.UNKNOWN) {
|
||||
if (appended++ > 0) validCodes.append(", ");
|
||||
validCodes.append(code.code);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Configured status code " + statusCode +
|
||||
" not supported! Please choose one of: " + validCodes.toString());
|
||||
}
|
||||
|
||||
// must always have a response message if sending an error code
|
||||
responseMsg = params.get("responseMessage", DEFAULT_RESPONSE_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateRequestProcessor getInstance(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next) {
|
||||
return new IgnoreCommitOptimizeUpdateProcessor(rsp, this, next);
|
||||
}
|
||||
}
|
||||
|
||||
class IgnoreCommitOptimizeUpdateProcessor extends UpdateRequestProcessor {
|
||||
|
||||
private final SolrQueryResponse rsp;
|
||||
private final ErrorCode errorCode;
|
||||
private final String responseMsg;
|
||||
private final boolean ignoreOptimizeOnly;
|
||||
|
||||
IgnoreCommitOptimizeUpdateProcessor(SolrQueryResponse rsp,
|
||||
IgnoreCommitOptimizeUpdateProcessorFactory factory,
|
||||
UpdateRequestProcessor next)
|
||||
{
|
||||
super(next);
|
||||
this.rsp = rsp;
|
||||
this.errorCode = factory.errorCode;
|
||||
this.responseMsg = factory.responseMsg;
|
||||
this.ignoreOptimizeOnly = factory.ignoreOptimizeOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommit(CommitUpdateCommand cmd) throws IOException {
|
||||
|
||||
if (ignoreOptimizeOnly && !cmd.optimize) {
|
||||
// we're setup to only ignore optimize requests so it's OK to pass this commit on down the line
|
||||
if (next != null) next.processCommit(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
final String cmdType = cmd.optimize ? "optimize" : "commit";
|
||||
if (errorCode != null) {
|
||||
IgnoreCommitOptimizeUpdateProcessorFactory.log.info(
|
||||
"{} from client application ignored with error code: {}", cmdType, errorCode.code);
|
||||
rsp.setException(new SolrException(errorCode, responseMsg));
|
||||
} else {
|
||||
// errorcode is null, treat as a success with an optional message warning the commit request was ignored
|
||||
IgnoreCommitOptimizeUpdateProcessorFactory.log.info(
|
||||
"{} from client application ignored with status code: 200", cmdType);
|
||||
if (responseMsg != null) {
|
||||
NamedList<Object> responseHeader = rsp.getResponseHeader();
|
||||
if (responseHeader != null) {
|
||||
responseHeader.add("msg", responseMsg);
|
||||
} else {
|
||||
responseHeader = new SimpleOrderedMap<Object>();
|
||||
responseHeader.add("msg", responseMsg);
|
||||
rsp.add("responseHeader", responseHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -512,4 +512,25 @@
|
|||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<updateRequestProcessorChain name="ignore-commit-from-client-403">
|
||||
<processor class="solr.IgnoreCommitOptimizeUpdateProcessorFactory"/>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<updateRequestProcessorChain name="ignore-commit-from-client-200">
|
||||
<processor class="solr.IgnoreCommitOptimizeUpdateProcessorFactory">
|
||||
<int name="statusCode">200</int>
|
||||
<str name="responseMessage">Thou shall not issue a commit!</str>
|
||||
</processor>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<updateRequestProcessorChain name="ignore-optimize-only-from-client-403">
|
||||
<processor class="solr.IgnoreCommitOptimizeUpdateProcessorFactory">
|
||||
<str name="responseMessage">Thou shall not issue an optimize, but commits are OK!</str>
|
||||
<bool name="ignoreOptimizeOnly">true</bool>
|
||||
</processor>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
</config>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package org.apache.solr.update.processor;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.common.SolrInputField;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrRequestInfo;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.update.AddUpdateCommand;
|
||||
import org.apache.solr.update.CommitUpdateCommand;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
public class IgnoreCommitOptimizeUpdateProcessorFactoryTest extends SolrTestCaseJ4 {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
initCore("solrconfig-update-processor-chains.xml", "schema.xml");
|
||||
}
|
||||
|
||||
public void testIgnoreCommit() throws Exception {
|
||||
// verify that the processor returns an error if it receives a commit
|
||||
SolrQueryResponse rsp = processCommit("ignore-commit-from-client-403", false);
|
||||
assertNotNull("Sending a commit should have resulted in an exception in the response", rsp.getException());
|
||||
|
||||
rsp = processCommit("ignore-commit-from-client-200", false);
|
||||
Exception shouldBeNull = rsp.getException();
|
||||
assertNull("Sending a commit should NOT have resulted in an exception in the response: "+shouldBeNull, shouldBeNull);
|
||||
|
||||
rsp = processCommit("ignore-optimize-only-from-client-403", true);
|
||||
assertNotNull("Sending an optimize should have resulted in an exception in the response", rsp.getException());
|
||||
}
|
||||
|
||||
SolrQueryResponse processCommit(final String chain, boolean optimize) throws IOException {
|
||||
SolrCore core = h.getCore();
|
||||
UpdateRequestProcessorChain pc = core.getUpdateProcessingChain(chain);
|
||||
assertNotNull("No Chain named: " + chain, pc);
|
||||
|
||||
SolrQueryResponse rsp = new SolrQueryResponse();
|
||||
SolrQueryRequest req = new LocalSolrQueryRequest(core, new ModifiableSolrParams());
|
||||
try {
|
||||
SolrRequestInfo.setRequestInfo(new SolrRequestInfo(req,rsp));
|
||||
CommitUpdateCommand cmd = new CommitUpdateCommand(req, false);
|
||||
cmd.optimize = optimize;
|
||||
UpdateRequestProcessor processor = pc.createProcessor(req, rsp);
|
||||
processor.processCommit(cmd);
|
||||
} finally {
|
||||
SolrRequestInfo.clearRequestInfo();
|
||||
req.close();
|
||||
}
|
||||
return rsp;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue