View Javadoc
1   package net.secodo.jcircuitbreaker.breakhandler;
2   
3   import net.secodo.jcircuitbreaker.breaker.CircuitBreaker;
4   import net.secodo.jcircuitbreaker.breaker.ContextAwareCircuitBreaker;
5   import net.secodo.jcircuitbreaker.breaker.execution.ExecutionContext;
6   import net.secodo.jcircuitbreaker.breakhandler.exception.BreakHandlerException;
7   import net.secodo.jcircuitbreaker.breakstrategy.BreakStrategy;
8   import net.secodo.jcircuitbreaker.task.Task;
9   
10  
11  /**
12   * An implementation of {@link BreakHandlerFactory} which creates new instance of given {@link BreakHandler} if it
13   * does not exist in current execution context, otherwise returns {@link BreakHandler} bound to current execution
14   * context (reuses the same instance for handling subsequent calls to
15   * {@link BreakHandler#onBreak(ContextAwareCircuitBreaker, Task, BreakStrategy, ExecutionContext)}).
16   *
17   * <p>NOTE: Each call to {@link CircuitBreaker#execute(Task, BreakStrategy, BreakHandler)} method creates new
18   * context.
19   * If implementation of {@link OnePerExecutionHandlerFactory} is used as a {@link BreakHandler}, "one and only one"
20   * instance of given {@link BreakHandler} is created for per execution context (this is guaranteed by default
21   * implementation of {@link #makeHandler(Task, ExecutionContext)} provided by this interface)
22   */
23  public interface OnePerExecutionHandlerFactory<R> extends BreakHandlerFactory<R> {
24    @Override
25    default BreakHandler<R> makeHandler(Task<R> task, ExecutionContext<R> executionContext)
26                                 throws BreakHandlerException {
27      String executionContextParamName = getOnePerExecutionContextParamName(task, executionContext);
28  
29      if (!executionContext.hasContextAttribute(executionContextParamName)) {
30        // no retry handler was create for current execution so we need to create it
31  
32        BreakHandler<R> breakHandler = createNewHandler(task, executionContext);
33        executionContext.setContextAttribute(executionContextParamName, breakHandler);
34      }
35  
36      return executionContext.getContextAttribute(executionContextParamName);
37    }
38  
39    /**
40     * Constructs and returns new {@link BreakHandler}. This method is invoked break handler has not yet been created in
41     * current execution context.
42     *
43     * @param task the originally executed task
44     * @param executionContext current execution context
45     * @return new instance of {@link BreakHandler}
46     */
47    BreakHandler<R> createNewHandler(Task<R> task, ExecutionContext<R> executionContext);
48  
49    /**
50     * Returns execution context parameter name under which produced break handler will be stored.
51     *
52     * @param task the originally executed task
53     * @param executionContext current execution context
54     *
55     * @see ExecutionContext#getContextAttribute(String)
56     * @return a String representing attribute name
57     */
58    default String getOnePerExecutionContextParamName(Task<R> task, ExecutionContext<R> executionContext) {
59      return "one_per_execution_handler_factory_" + this.getClass().getName();
60    }
61  }