Index: oak-solr-core/pom.xml =================================================================== --- oak-solr-core/pom.xml (revision 1574838) +++ oak-solr-core/pom.xml (working copy) @@ -121,12 +121,6 @@ tests - javax.servlet - servlet-api - 2.5 - test - - org.apache.jackrabbit oak-mk ${project.version} Index: oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServer.java =================================================================== --- oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServer.java (revision 0) +++ oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServer.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.jackrabbit.oak.plugins.index.solr.server; + +import java.io.IOException; +import java.util.Queue; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.common.util.NamedList; + +/** + * A {@link org.apache.solr.client.solrj.SolrServer} wrapper which caches requests if the Solr instance / cluster, + * represented by a 'root' {@link org.apache.solr.client.solrj.SolrServer}, is not reachable. + */ +public class RequestCachingSolrServer extends SolrServer { + private final SolrServer solrServer; + private final ExecutorService executorService; + private final Queue queue = new ConcurrentLinkedQueue(); + private final boolean blocking; + + public RequestCachingSolrServer(SolrServer solrServer, ExecutorService executorService, boolean blocking) { + this.solrServer = solrServer; + this.executorService = executorService; + this.blocking = blocking; + } + + public RequestCachingSolrServer(SolrServer solrServer, ExecutorService executorService) { + this.solrServer = solrServer; + this.executorService = executorService; + blocking = true; + } + + private boolean isSolrReachable() { + try { + return 0 == solrServer.ping().getStatus(); + } catch (Exception e) { + return false; + } + } + + @Override + public NamedList request(final SolrRequest request) throws SolrServerException, IOException { + NamedList response = null; + synchronized (queue) { + if (queue.isEmpty() && isSolrReachable()) { + response = solrServer.request(request); + } else { + SolrServerCommand> command = new SolrServerCommand>() { + @Override + public NamedList execute() throws Exception { + return solrServer.request(request); + } + }; + queue.add(command); + try { + Future> future = executorService.submit(new SolrServerCommandCallable>(command)); + if (blocking) { + response = future.get(); + } + } catch (Exception e) { + // do nothing + } + } + } + return response; + } + + @Override + public void shutdown() { + executorService.shutdown(); + queue.clear(); + solrServer.shutdown(); + } + + private interface SolrServerCommand { + T execute() throws Exception; + } + + private class SolrServerCommandCallable implements Callable { + + private SolrServerCommand solrServerCommand; + + private SolrServerCommandCallable(SolrServerCommand solrServerCommand) { + this.solrServerCommand = solrServerCommand; + } + + @Override + public T call() throws Exception { + synchronized (queue) { + while (true) { + if (solrServerCommand.equals(queue.element()) && isSolrReachable()) { + T result = null; + try { + result = solrServerCommand.execute(); + } catch (Exception e) { + // could not execute the command + } + if (result != null) { + queue.remove(); + return result; + } + } else { + Thread.sleep(3000); + } + } + } + } + } +} \ No newline at end of file Property changes on: oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServer.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServerTest.java =================================================================== --- oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServerTest.java (revision 0) +++ oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServerTest.java (working copy) @@ -0,0 +1,75 @@ +/* + * 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.jackrabbit.oak.plugins.index.solr.server; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.concurrent.Executors; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.embedded.JettySolrRunner; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.apache.solr.common.SolrInputDocument; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Testcase for {@link org.apache.jackrabbit.oak.plugins.index.solr.server.RequestCachingSolrServer} + */ +public class RequestCachingSolrServerTest { + + @Test + public void testResilience() throws Exception { + + JettySolrRunner jettySolrRunner = new JettySolrRunner(getClass().getResource("/solr").getFile(), "/solr", 8983, "solrconfig.xml", null, true, null, null); + jettySolrRunner.start(); + + SolrServer httpSolrServer = new HttpSolrServer("http://localhost:8983/solr/oak"); + + Collection docs = new LinkedList(); + SolrInputDocument doc = new SolrInputDocument(); + doc.addField("path_exact", "/a"); + doc.addField("text", "foo"); + docs.add(doc); + doc = new SolrInputDocument(); + doc.addField("path_exact", "/b"); + doc.addField("text", "bar"); + docs.add(doc); + + RequestCachingSolrServer requestCachingSolrServer = new RequestCachingSolrServer(httpSolrServer, Executors.newCachedThreadPool(), false); + requestCachingSolrServer.add(docs); + requestCachingSolrServer.commit(); + + assertEquals(2, httpSolrServer.query(new SolrQuery("text:(foo bar)")).getResults().size()); + + jettySolrRunner.stop(); + + docs.clear(); + doc = new SolrInputDocument(); + doc.addField("path_exact", "/c"); + doc.addField("text", "xyz"); + docs.add(doc); + requestCachingSolrServer.add(docs); + requestCachingSolrServer.commit(); + + jettySolrRunner.start(); + + Thread.sleep(10000); + assertEquals(1, httpSolrServer.query(new SolrQuery("text:xyz")).getResults().size()); + } +} Property changes on: oak-solr-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/server/RequestCachingSolrServerTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property