
com.bazaarvoice.ostrich.pool.AsyncServicePool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ostrich-core Show documentation
Show all versions of ostrich-core Show documentation
Core classes that form Ostrich
package com.bazaarvoice.ostrich.pool;
import com.bazaarvoice.ostrich.PartitionContext;
import com.bazaarvoice.ostrich.RetryPolicy;
import com.bazaarvoice.ostrich.ServiceCallback;
import com.bazaarvoice.ostrich.ServiceEndPoint;
import com.bazaarvoice.ostrich.ServiceEndPointPredicate;
import com.bazaarvoice.ostrich.exceptions.MaxRetriesException;
import com.bazaarvoice.ostrich.exceptions.NoAvailableHostsException;
import com.bazaarvoice.ostrich.metrics.Metrics;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.google.common.base.Ticker;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;
class AsyncServicePool implements com.bazaarvoice.ostrich.AsyncServicePool {
private static final Logger LOG = LoggerFactory.getLogger(AsyncServicePool.class);
private static final ServiceEndPointPredicate ALL_END_POINTS = new ServiceEndPointPredicate() {
@Override
public boolean apply(ServiceEndPoint endPoint) {
return true;
}
};
private final Ticker _ticker;
private final ServicePool _pool;
private final boolean _shutdownPoolOnClose;
private final ExecutorService _executor;
private final boolean _shutdownExecutorOnClose;
private final Metrics.InstanceMetrics _metrics;
private final Timer _executionTime;
private final Meter _numExecuteSuccesses;
private final Meter _numExecuteFailures;
private final Histogram _executeBatchSize;
AsyncServicePool(Ticker ticker, ServicePool pool, boolean shutdownPoolOnClose,
ExecutorService executor, boolean shutdownExecutorOnClose, MetricRegistry metrics) {
_ticker = checkNotNull(ticker);
_pool = checkNotNull(pool);
_shutdownPoolOnClose = shutdownPoolOnClose;
_executor = checkNotNull(executor);
_shutdownExecutorOnClose = shutdownExecutorOnClose;
_metrics = Metrics.forInstance(metrics, this, _pool.getServiceName());
_executionTime = _metrics.timer("execution-time");
_numExecuteSuccesses = _metrics.meter("num-execute-successes");
_numExecuteFailures = _metrics.meter("num-execute-failures");
_executeBatchSize = _metrics.histogram("execute-batch-size");
}
@Override
public void close() throws IOException {
if (_shutdownExecutorOnClose) {
_executor.shutdown();
}
if (_shutdownPoolOnClose) {
_pool.close();
}
_metrics.close();
}
@Override
public Future execute(final RetryPolicy retryPolicy, final ServiceCallback callback) {
return _executor.submit(new Callable() {
@Override
public R call() throws Exception {
return _pool.execute(retryPolicy, callback);
}
});
}
@Override
public Future execute(final PartitionContext partitionContext, final RetryPolicy retryPolicy,
final ServiceCallback callback) {
return _executor.submit(new Callable() {
@Override
public R call() throws Exception {
return _pool.execute(partitionContext, retryPolicy, callback);
}
});
}
@Override
public Collection> executeOnAll(RetryPolicy retry, ServiceCallback callback) {
return executeOn(ALL_END_POINTS, retry, callback);
}
@Override
public Collection> executeOn(ServiceEndPointPredicate predicate, final RetryPolicy retry,
final ServiceCallback callback) {
Collection> futures = Lists.newArrayList();
Iterable endPoints = _pool.getAllEndPoints();
if (Iterables.isEmpty(endPoints)) {
throw new NoAvailableHostsException();
}
for (final ServiceEndPoint endPoint : endPoints) {
if (!predicate.apply(endPoint)) {
continue;
}
Future future = _executor.submit(new Callable() {
@Override
public R call() throws Exception {
Timer.Context timer = _executionTime.time();
final long start = _ticker.read();
int numAttempts = 0;
try {
Exception lastException;
do {
try {
R result = _pool.executeOnEndPoint(endPoint, callback);
_numExecuteSuccesses.mark();
return result;
} catch (Exception e) {
_numExecuteFailures.mark();
// Don't retry if exception is too severe.
if (!_pool.isRetriableException(e)) {
throw e;
}
lastException = e;
LOG.info("Retriable exception from end point id: " + endPoint.getId(), e);
}
} while (retry.allowRetry(++numAttempts, TimeUnit.NANOSECONDS.toMillis(_ticker.read() - start)));
throw new MaxRetriesException(lastException);
} finally {
timer.stop();
}
}
});
futures.add(future);
}
_executeBatchSize.update(futures.size());
return futures;
}
@Override
public int getNumValidEndPoints() {
return _pool.getNumValidEndPoints();
}
@Override
public int getNumBadEndPoints() {
return _pool.getNumBadEndPoints();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy