LimitedConcurrentExecutionsStrategy.java

package net.secodo.jcircuitbreaker.breakstrategy.impl;

import java.util.Collection;

import net.secodo.jcircuitbreaker.breaker.execution.ExecutedTask;
import net.secodo.jcircuitbreaker.breaker.execution.ExecutionContext;
import net.secodo.jcircuitbreaker.breakstrategy.BreakStrategy;
import net.secodo.jcircuitbreaker.task.Task;


/**
 * An implementation of {@link BreakStrategy} which causes the circuit breaker to break (not execute the Task) in
 * case all tasks currently running inside the circuit breaker reaches the allowed maximum (defined by
 * maxSupportedExecutions constructor param).
 *
 * <p>In constructor you define maximum number of allowed concurrent executions of <i>real_method</i> .
 *
 * <p>For example this strategy:
 *
 * <p>new LimitedConcurrentExecutionsStrategy(10);
 *
 * <p>breaks (not allows execution of target-method) in there are currently 10 other threads that started execution
 * of <i>target-method</i> and the method did not yet return a value. In this case circuit breaker would executed a
 * break handler to provide fallback behaviour. If the number of task at the moment was less than 10, <i>Task</i>
 * (<i>real-method</i>) would be executed normal.
 *
 * <p>NOTE: in above example, if the average was above 1000ms than this strategy would return false to circuit breaker
 * and circuit breaker would execute {@link net.secodo.jcircuitbreaker.breakhandler.BreakHandler} to handle this
 * situation
 *
 * @param <R> the return type of <i>real-method</i> that is executed by circuit breaker
 */
public class LimitedConcurrentExecutionsStrategy<R> implements BreakStrategy<R> {
  /**
   * Protected access to allow extending classes to dynamically change it,
   * e.g. via MBean
   */
  protected long maxSupportedExecutions;

  public LimitedConcurrentExecutionsStrategy(long maxSupportedExecutions) {
    this.maxSupportedExecutions = maxSupportedExecutions;
  }


  @Override
  public boolean shouldBreak(Task<R> task, ExecutionContext<R> executionContext) {
    final Collection<ExecutedTask<R>> executionsInProgress = executionContext.getExecutionsInProgress();

    return executionsInProgress.size() >= maxSupportedExecutions;
  }
}