OnePerExecutionHandlerFactory.java
package net.secodo.jcircuitbreaker.breakhandler;
import net.secodo.jcircuitbreaker.breaker.CircuitBreaker;
import net.secodo.jcircuitbreaker.breaker.ContextAwareCircuitBreaker;
import net.secodo.jcircuitbreaker.breaker.execution.ExecutionContext;
import net.secodo.jcircuitbreaker.breakhandler.exception.BreakHandlerException;
import net.secodo.jcircuitbreaker.breakstrategy.BreakStrategy;
import net.secodo.jcircuitbreaker.task.Task;
/**
* An implementation of {@link BreakHandlerFactory} which creates new instance of given {@link BreakHandler} if it
* does not exist in current execution context, otherwise returns {@link BreakHandler} bound to current execution
* context (reuses the same instance for handling subsequent calls to
* {@link BreakHandler#onBreak(ContextAwareCircuitBreaker, Task, BreakStrategy, ExecutionContext)}).
*
* <p>NOTE: Each call to {@link CircuitBreaker#execute(Task, BreakStrategy, BreakHandler)} method creates new
* context.
* If implementation of {@link OnePerExecutionHandlerFactory} is used as a {@link BreakHandler}, "one and only one"
* instance of given {@link BreakHandler} is created for per execution context (this is guaranteed by default
* implementation of {@link #makeHandler(Task, ExecutionContext)} provided by this interface)
*/
public interface OnePerExecutionHandlerFactory<R> extends BreakHandlerFactory<R> {
@Override
default BreakHandler<R> makeHandler(Task<R> task, ExecutionContext<R> executionContext)
throws BreakHandlerException {
String executionContextParamName = getOnePerExecutionContextParamName(task, executionContext);
if (!executionContext.hasContextAttribute(executionContextParamName)) {
// no retry handler was create for current execution so we need to create it
BreakHandler<R> breakHandler = createNewHandler(task, executionContext);
executionContext.setContextAttribute(executionContextParamName, breakHandler);
}
return executionContext.getContextAttribute(executionContextParamName);
}
/**
* Constructs and returns new {@link BreakHandler}. This method is invoked break handler has not yet been created in
* current execution context.
*
* @param task the originally executed task
* @param executionContext current execution context
* @return new instance of {@link BreakHandler}
*/
BreakHandler<R> createNewHandler(Task<R> task, ExecutionContext<R> executionContext);
/**
* Returns execution context parameter name under which produced break handler will be stored.
*
* @param task the originally executed task
* @param executionContext current execution context
*
* @see ExecutionContext#getContextAttribute(String)
* @return a String representing attribute name
*/
default String getOnePerExecutionContextParamName(Task<R> task, ExecutionContext<R> executionContext) {
return "one_per_execution_handler_factory_" + this.getClass().getName();
}
}