package com.lucidworks.storm.solr;
import com.codahale.metrics.Counter;
import com.ryantenney.metrics.annotation.Metric;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.NamedList;
import java.net.ConnectException;
import java.net.SocketException;
/**
* Bean that sends an update request to Solr with tunable retry support.
* The default implementation should be sufficient for most purposes but
* you can inject a different implementation using Spring.
*/
public class DefaultUpdateRequestStrategy implements SolrUpdateRequestStrategy {
public static Logger log = Logger.getLogger(DefaultUpdateRequestStrategy.class);
@Metric
public Counter okRequests;
@Metric
public Counter retriedRequests;
@Metric
public Counter failedRequests;
protected int waitSecsBetweenRetries = 5;
protected int maxRetryAttempts = 1;
public NamedList<Object> sendUpdateRequest(SolrClient solrClient, String collection, SolrRequest req) {
return sendUpdateRequestWithRetry(solrClient, collection, req, maxRetryAttempts);
}
protected NamedList<Object> sendUpdateRequestWithRetry(SolrClient solrClient, String collection, SolrRequest req, int remainingRetryAttempts) {
NamedList<Object> resp = null;
try {
resp = solrClient.request(req);
if (okRequests != null)
okRequests.inc();
} catch (Exception e) {
if (remainingRetryAttempts <= 0) {
log.error("Send update request to "+collection+" failed due to " + e +
"; max number of re-try attempts "+maxRetryAttempts+" reached, no more attempts available, request fails!");
if (failedRequests != null)
failedRequests.inc();
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}
if (shouldRetry(e)) {
log.error("Send update request to "+collection+" failed due to " + e +
"; will retry after waiting "+waitSecsBetweenRetries+" secs");
try {
Thread.sleep(waitSecsBetweenRetries * 1000L);
} catch (InterruptedException ie) {
Thread.interrupted();
}
try {
sendUpdateRequestWithRetry(solrClient, collection, req, --remainingRetryAttempts);
} finally {
if (retriedRequests != null)
retriedRequests.inc();
}
} else {
log.error("Send update request to collection " + collection + " failed due to: " + e+
", which cannot be retried, request fails!", e);
if (failedRequests != null)
failedRequests.inc();
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}
}
return resp;
}
public int getWaitSecsBetweenRetries() {
return waitSecsBetweenRetries;
}
public void setWaitSecsBetweenRetries(int waitSecsBetweenRetries) {
this.waitSecsBetweenRetries = waitSecsBetweenRetries;
}
public int getMaxRetryAttempts() {
return maxRetryAttempts;
}
public void setMaxRetryAttempts(int maxRetryAttempts) {
this.maxRetryAttempts = maxRetryAttempts;
}
protected boolean shouldRetry(Exception exc) {
Throwable rootCause = SolrException.getRootCause(exc);
return (rootCause instanceof ConnectException || rootCause instanceof SocketException);
}
}