Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package org.apache.solr.client.solrj.impl;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -35,6 +34,8 @@
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.SolrResponseBase;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.embedded.JettyConfig;
import org.apache.solr.embedded.JettySolrRunner;
import org.apache.solr.util.LogLevel;
Expand Down Expand Up @@ -110,7 +111,12 @@ private void addDocs(SolrInstance solrInstance) throws IOException, SolrServerEx
public void tearDown() throws Exception {
for (SolrInstance aSolr : solr) {
if (aSolr != null) {
aSolr.tearDown();
try {
aSolr.tearDown();
} catch (Exception e) {
// Log but don't fail the test due to teardown issues
log.warn("Exception during tearDown of {}", aSolr.name, e);
}
}
}
super.tearDown();
Expand Down Expand Up @@ -159,8 +165,17 @@ public void testSimple() throws Exception {
assertEquals(3, names.size());

// Kill a server and test again
solr[1].jetty.stop();
solr[1].jetty = null;
try {
solr[1].jetty.stop();
} catch (Exception e) {
log.warn("Exception stopping jetty during test", e);
} finally {
solr[1].jetty = null;
}

// Give some time for the LB client to detect the server is down
Thread.sleep(100);

names.clear();
for (int i = 0; i < solr.length; i++) {
resp = h.lbClient.query(solrQuery);
Expand All @@ -187,17 +202,32 @@ public void testTwoServers() throws Exception {
try (var h = client(baseSolrEndpoints)) {
SolrQuery solrQuery = new SolrQuery("*:*");
QueryResponse resp = null;
solr[0].jetty.stop();
solr[0].jetty = null;

try {
solr[0].jetty.stop();
} catch (Exception e) {
log.warn("Exception stopping jetty[0] during test", e);
} finally {
solr[0].jetty = null;
}

Thread.sleep(100); // Give LB client time to detect server down

resp = h.lbClient.query(solrQuery);
String name = resp.getResults().get(0).getFieldValue("name").toString();
assertEquals("solr/collection11", name);
resp = h.lbClient.query(solrQuery);
name = resp.getResults().get(0).getFieldValue("name").toString();
assertEquals("solr/collection11", name);

solr[1].jetty.stop();
solr[1].jetty = null;
try {
solr[1].jetty.stop();
} catch (Exception e) {
log.warn("Exception stopping jetty[1] during test", e);
} finally {
solr[1].jetty = null;
}

startJettyAndWaitForAliveCheckQuery(solr[0]);

resp = h.lbClient.query(solrQuery);
Expand All @@ -224,6 +254,33 @@ private void startJettyAndWaitForAliveCheckQuery(SolrInstance solrInstance) thro
}
}

private static void stopJettyWithTimeout(JettySolrRunner jetty, long timeoutMs) throws Exception {
final var executor =
ExecutorUtil.newMDCAwareSingleThreadExecutor(new SolrNamedThreadFactory("jetty-shutdown"));

try {
final var future =
java.util.concurrent.CompletableFuture.runAsync(
() -> {
try {
jetty.stop();
} catch (Exception e) {
throw new RuntimeException(e);
}
},
executor);

try {
future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (java.util.concurrent.TimeoutException e) {
future.cancel(true);
throw new Exception("Jetty shutdown timed out after " + timeoutMs + "ms", e);
}
} finally {
executor.shutdown();
}
}

private static class SolrInstance {
String name;
Path homeDir;
Expand Down Expand Up @@ -292,7 +349,16 @@ public void setUp() throws Exception {
}

public void tearDown() throws Exception {
if (jetty != null) jetty.stop();
if (jetty != null) {
try {
// Use a timeout wrapper for shutdown
stopJettyWithTimeout(jetty, 5000);
} catch (Exception e) {
log.warn("Exception stopping jetty for {}", name, e);
} finally {
jetty = null;
}
}
IOUtils.rm(homeDir);
}

Expand Down Expand Up @@ -326,11 +392,16 @@ private static class LBClientHolder implements AutoCloseable {

@Override
public void close() {
lbClient.close();
try {
lbClient.close();
} catch (Exception e) {
log.warn("Exception closing LB client", e);
}
try {
delegate.close();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
log.warn("Exception closing delegate client", ioe);
// Don't throw exception during cleanup to avoid masking test failures
}
}
}
Expand Down