package com.bazaarvoice.ostrich;
import java.io.Closeable;
/**
* A <code>ServicePool</code> keeps track of service end points for a particular service. Internally it
* understands how requests should be load balanced across end points and takes a service owner's
* <code>LoadBalanceAlgorithm</code> into account when deciding which end point to use. In addition the
* <code>ServicePool</code> is also able to monitor the health of a service end point if the service owner provides a
* health check implementation. It is able to use the health check information as a guide in selecting service
* end points in order to avoid providing an unhealthy service end point to a user.
* <p/>
* The <code>ServicePool</code> provides an automatically managed resource pool model to consumers. A consumer
* provides a callback to the <code>ServicePool</code> to execute a piece of code against a service end point. The
* <code>ServicePool</code> will then select a suitable service end point to use and then invoke the user's callback
* with a handle to the end point. At that point the user can interact with the remote end point however it wants,
* calling any APIs necessary. When the callback returns, the connection with the remote service is cleaned up. If
* during the execution of the callback a service related error occurs, the service end point will be marked as
* unhealthy, and the operation retried, as allowed by the <code>RetryPolicy</code> the user specifies.
* <p/>
* For example, assume that we have a mythical <code>CalculatorService</code> with <code>add</code>, <code>sub</code>,
* etc. methods on it. Usage of a <code>ServicePool</code> for that service might look like:
* <pre>
* int sum = calculatorPool.execute(new RetryNTimes(3), new ServiceCallback<CalculatorService, Integer>() {
* public Integer call(CalculatorService calculator) {
* return calculator.add(1, calculator.sub(3, 2));
* }
* });
* </pre>
*
* @param <S> The service interface that this pool keeps track of end points for.
*/
public interface ServicePool<S> extends Closeable {
/**
* Execute a request synchronously against one of the remote services in this <code>ServicePool</code>.
*
* @param retryPolicy The retry policy for the operation.
* @param callback The user provided callback to invoke with a service end point.
* @param <R> The return type for the call.
* @return The result provided by the callback.
*/
<R> R execute(RetryPolicy retryPolicy, ServiceCallback<S, R> callback);
/**
* Execute a request synchronously against one of the remote services in this <code>ServicePool</code> using
* the specified partition information to narrow down the suitable service end points.
*
* @param partitionContext The partition context.
* @param retryPolicy The retry policy for the operation.
* @param callback The user provided callback to invoke with a service end point.
* @param <R> The return type for the call.
* @return The result provided by the callback.
*/
<R> R execute(PartitionContext partitionContext, RetryPolicy retryPolicy, ServiceCallback<S, R> callback);
/**
* Attempts to find a healthy end point. Performs health checks until a healthy end point is found, all available
* end points are exhausted, or execution of a health check throws an exception that is deemed not retriable.
*
* @return {@code HealthCheckResults} containing the first healthy result found (if any), and all unhealthy results
* encountered before a healthy one. If there are no end points in the pool, the {@code HealthCheckResults} will
* contain no results.
*/
HealthCheckResults checkForHealthyEndPoint();
/**
* Return the number of valid end points that this service pool knows about. This will include end points that have
* never thrown exceptions during execution (even those that have never been interacted with) and end points that
* were previously known as bad but have since had a successful health check. If this method returns non-zero, then
* a call to execute should not fail with an {@link com.bazaarvoice.ostrich.exceptions.OnlyBadHostsException} or
* {@link com.bazaarvoice.ostrich.exceptions.NoAvailableHostsException} exception.
*/
int getNumValidEndPoints();
/**
* Return the number of end points that this service pool considers to be in a bad state. A bad end point is one
* that a previous operation was attempted on and the attempt failed. An end point could be considered bad prior to
* its health check being called.
* <p/>
* This combined with {@link #getNumValidEndPoints()} gives visibility into the total number of end points that the
* {@code ServicePool} knows about.
*/
int getNumBadEndPoints();
}