Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support execution listener for Ribbon transport clients #146

Closed
allenxwang opened this issue Jul 26, 2014 · 1 comment
Closed

Support execution listener for Ribbon transport clients #146

allenxwang opened this issue Jul 26, 2014 · 1 comment

Comments

@allenxwang
Copy link

Ribbon transport clients use load balancer to execute a request for most of the use cases. When load balancer executes the request, it may involve with multiple servers and multiple retries on each server in order to fulfill the request. It will be nice to hook into this execution cycle with a listener to get notified of each execution event. This enables tracing on request level. Also, the listener mechanism allows loose coupling of logics that are not central to the execution of the network call like logging and statistics gathering.

Here is the high level interface design:

/**
 * A context object that is created at start of each load balancer execution
 * and contains certain meta data of the load balancer and mutable state data of 
 * execution per listener per request. Each listener will get its own context
 * to work with. But it can also call {@link ExecutionContext#getGlobalContext()} to
 * get the shared context between all listeners.
 * 
 */
public class ExecutionContext<T> {
    public T getRequest();

    public Object get(String name);

    public <S> S getClientProperty(IClientConfigKey<S> key);

    public void put(String name, Object value) ;

    /**
     * @return The IClientConfig object used to override the client's default configuration
     * for this specific execution.
     */
    public IClientConfig getRequestConfig();

    /**
     *
     * @return The shared context for all listeners.
     */
    public ExecutionContext<T> getGlobalContext();

    public RetryHandler getRetryHandler();
}

/**
 * Represents the state of execution for an instance of {@link com.netflix.loadbalancer.reactive.LoadBalancerObservableCommand}
 * and is passed to {@link ExecutionListener}
 */
public class ExecutionInfo {

    public Server getServer();

    public int getNumberOfPastAttemptsOnServer();

    public int getNumberOfPastServersAttempted();
}

/**
 * A listener to be invoked by load balancer at different stage of execution.
 *
 * @param <I> Input type used by {@link ExecutionContext} passed to
 *           listener where it can call {@link ExecutionContext#getRequest()} to examine the
 *           request object of the execution
 * @param <O> Output type from the load balancer execution, used by {@link #onExecutionSuccess(ExecutionContext, Object, com.netflix.loadbalancer.reactive.ExecutionInfo)}
 *           API
 */
public interface ExecutionListener<I, O> {

    /**
     * An exception to indicate that the listener wants to abort execution
     */
    class AbortExecutionException extends RuntimeException {
        public AbortExecutionException(String message) {
            super(message);
        }

        public AbortExecutionException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    /**
     * Called when execution is about to start.
     *
     * @throws ExecutionListener.AbortExecutionException if the listener would
     *              like to abort the execution
     */
    public void onExecutionStart(ExecutionContext<I> context) throws AbortExecutionException;

    /**
     * Called when a server is chosen and the request is going to be executed on the server.
     *
     * @throws ExecutionListener.AbortExecutionException if the listener would
     *              like to abort the execution
     */
    public void onStartWithServer(ExecutionContext<I> context, ExecutionInfo info) throws AbortExecutionException;

    /**
     * Called when an exception is received from executing the request on a server. 
     * 
     * @param exception Exception received
     */
    public void onExceptionWithServer(ExecutionContext<I> context, Throwable exception,  ExecutionInfo info);

    /**
     * Called when the request is executed successfully on the server
     * 
     * @param response Object received from the execution
     */
    public void onExecutionSuccess(ExecutionContext<I> context, O response,  ExecutionInfo info);

    /**
     * Called when the request is considered failed after all retries.
     * 
     * @param finalException Final exception received. This may be a wrapped exception indicating that all
     *                       retries have been exhausted.
     */
    public void onExecutionFailed(ExecutionContext<I> context, Throwable finalException, ExecutionInfo info);
}
@allenxwang
Copy link
Author

Addressed in ribbon 2.0-RC9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant