content: /*
   * Copyright 1999-2022 Alibaba Group Holding Ltd.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.alibaba.csp.sentinel.slots.block.degrade;
  
  import com.alibaba.csp.sentinel.Constants;
  import com.alibaba.csp.sentinel.Entry;
  import com.alibaba.csp.sentinel.context.Context;
  import com.alibaba.csp.sentinel.node.DefaultNode;
  import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
  import com.alibaba.csp.sentinel.slotchain.ProcessorSlot;
  import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
  import com.alibaba.csp.sentinel.slots.block.BlockException;
  import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker;
  import com.alibaba.csp.sentinel.spi.Spi;
  
  import java.util.List;
  
  /**
   * <p>A {@link ProcessorSlot} dedicates to universal default circuit breaker.</p>
   *
   * @author wuwen
   * @since 2.0.0
   */
  @Spi(order = Constants.ORDER_DEFAULT_CIRCUIT_BREAKER_SLOT)
  public class DefaultCircuitBreakerSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
  
      @Override
      public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                        boolean prioritized, Object... args) throws Throwable {
          performChecking(context, resourceWrapper);
  
          fireEntry(context, resourceWrapper, node, count, prioritized, args);
      }
  
      private void performChecking(Context context, ResourceWrapper r) throws BlockException {
          // If user has set a degrade rule for the resource, the default rule will not be activated
          if (DegradeRuleManager.hasConfig(r.getName())) {
              return;
          }
  
          List<CircuitBreaker> circuitBreakers = DefaultCircuitBreakerRuleManager.getDefaultCircuitBreakers(r.getName());
  
          if (circuitBreakers == null || circuitBreakers.isEmpty()) {
              return;
          }
  
          for (CircuitBreaker cb : circuitBreakers) {
              if (!cb.tryPass(context)) {
                  throw new DegradeException(cb.getRule().getLimitApp(), cb.getRule());
              }
          }
      }
  
      @Override
      public void exit(Context context, ResourceWrapper r, int count, Object... args) {
          Entry curEntry = context.getCurEntry();
          if (curEntry.getBlockError() != null) {
              fireExit(context, r, count, args);
              return;
          }
  
          if (DegradeRuleManager.hasConfig(r.getName())) {
              fireExit(context, r, count, args);
              return;
          }
  
          List<CircuitBreaker> circuitBreakers = DefaultCircuitBreakerRuleManager.getDefaultCircuitBreakers(r.getName());
  
          if (circuitBreakers == null || circuitBreakers.isEmpty()) {
              fireExit(context, r, count, args);
              return;
          }
  
          if (curEntry.getBlockError() == null) {
              // passed request
              for (CircuitBreaker circuitBreaker : circuitBreakers) {
                  circuitBreaker.onRequestComplete(context);
              }
          }
  
          fireExit(context, r, count, args);
      }
  }
  