cpoerschke commented on code in PR #1919:
URL: https://github.com/apache/solr/pull/1919#discussion_r1385267122


##########
solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java:
##########
@@ -33,39 +35,47 @@
  * We depend on OperatingSystemMXBean which does not allow a configurable 
interval of collection of
  * data.
  */
-public class CPUCircuitBreaker extends CircuitBreaker {
+public class CPUCircuitBreaker extends CircuitBreaker implements SolrCoreAware 
{
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  private boolean enabled = true;
+  private Boolean enabled = null;
   private double cpuUsageThreshold;
-  private final SolrCore core;
+  private CoreContainer cc;
 
   private static final ThreadLocal<Double> seenCPUUsage = 
ThreadLocal.withInitial(() -> 0.0);
 
   private static final ThreadLocal<Double> allowedCPUUsage = 
ThreadLocal.withInitial(() -> 0.0);
 
-  public CPUCircuitBreaker(SolrCore core) {
+  public CPUCircuitBreaker() {
     super();
-    this.core = core;
+  }
+
+  public CPUCircuitBreaker(CoreContainer coreContainer) {
+    super();
+    this.cc = coreContainer;
   }
 
   @Override
   public void init(NamedList<?> args) {
     super.init(args);
-    double localSeenCPUUsage = calculateLiveCPUUsage();
-
-    if (localSeenCPUUsage < 0) {
-      String msg =
-          "Initialization failure for CPU circuit breaker. Unable to get 
'systemCpuLoad', not supported by the JVM?";
-      if (log.isErrorEnabled()) {
-        log.error(msg);
-      }
-      enabled = false;
-    }
   }

Review Comment:
   Can remove `init` then in favour of super method only.



##########
solr/core/src/java/org/apache/solr/util/circuitbreaker/CircuitBreakerRegistry.java:
##########
@@ -111,43 +199,82 @@ public static String toErrorMessage(List<CircuitBreaker> 
circuitBreakerList) {
   }
 
   public boolean isEnabled(SolrRequestType requestType) {
-    return circuitBreakerMap.containsKey(requestType);
+    return circuitBreakerMap.containsKey(requestType)
+        || globalCircuitBreakerMap.containsKey(requestType);
   }
 
   @Override
   public void close() throws IOException {
     synchronized (circuitBreakerMap) {
-      final AtomicInteger closeFailedCounter = new AtomicInteger(0);
-      circuitBreakerMap
-          .values()
-          .forEach(
-              list ->
-                  list.forEach(
-                      it -> {
-                        try {
-                          if (log.isDebugEnabled()) {
-                            log.debug(
-                                "Closed circuit breaker {} for request type(s) 
{}",
-                                it.getClass().getSimpleName(),
-                                it.getRequestTypes());
-                          }
-                          it.close();
-                        } catch (IOException e) {
-                          if (log.isErrorEnabled()) {
-                            log.error(
-                                String.format(
-                                    Locale.ROOT,
-                                    "Failed to close circuit breaker %s",
-                                    it.getClass().getSimpleName()),
-                                e);
-                          }
-                          closeFailedCounter.incrementAndGet();
-                        }
-                      }));
+      closeCircuitBreakers(
+          
circuitBreakerMap.values().stream().flatMap(List::stream).collect(Collectors.toList()));
       circuitBreakerMap.clear();
-      if (closeFailedCounter.get() > 0) {
-        throw new IOException("Failed to close " + closeFailedCounter.get() + 
" circuit breakers");
-      }
     }
   }
+
+  private static void closeGlobal() {
+    synchronized (globalCircuitBreakerMap) {
+      closeCircuitBreakers(
+          globalCircuitBreakerMap.values().stream()
+              .flatMap(List::stream)
+              .collect(Collectors.toList()));
+      globalCircuitBreakerMap.clear();
+    }
+  }
+
+  /**
+   * Close a list of circuit breakers, tracing any failures.
+   *
+   * @throws SolrException if any CB fails to close
+   */
+  private static void closeCircuitBreakers(List<CircuitBreaker> breakers) {
+    final AtomicInteger closeFailedCounter = new AtomicInteger(0);
+    breakers.forEach(
+        it -> {
+          try {
+            if (log.isDebugEnabled()) {
+              log.debug(
+                  "Closed circuit breaker {} for request type(s) {}",
+                  it.getClass().getSimpleName(),
+                  it.getRequestTypes());
+            }
+            it.close();
+          } catch (IOException e) {
+            if (log.isErrorEnabled()) {
+              log.error(
+                  String.format(
+                      Locale.ROOT,
+                      "Failed to close circuit breaker %s",
+                      it.getClass().getSimpleName()),

Review Comment:
   In case of ambiguity e.g. a global search CB and a per-core update CB or so.
   ```suggestion
                         "Failed to close circuit breaker %s for request 
type(s) {}",
                         it.getClass().getSimpleName(),
                         it.getRequestTypes()),
   ```



##########
solr/core/src/java/org/apache/solr/util/circuitbreaker/CircuitBreakerRegistry.java:
##########
@@ -111,43 +199,82 @@ public static String toErrorMessage(List<CircuitBreaker> 
circuitBreakerList) {
   }
 
   public boolean isEnabled(SolrRequestType requestType) {
-    return circuitBreakerMap.containsKey(requestType);
+    return circuitBreakerMap.containsKey(requestType)
+        || globalCircuitBreakerMap.containsKey(requestType);

Review Comment:
   ```suggestion
       return globalCircuitBreakerMap.containsKey(requestType)
           || circuitBreakerMap.containsKey(requestType);
   ```



##########
solr/core/src/java/org/apache/solr/util/circuitbreaker/CircuitBreakerRegistry.java:
##########
@@ -111,43 +199,82 @@ public static String toErrorMessage(List<CircuitBreaker> 
circuitBreakerList) {
   }
 
   public boolean isEnabled(SolrRequestType requestType) {
-    return circuitBreakerMap.containsKey(requestType);
+    return circuitBreakerMap.containsKey(requestType)
+        || globalCircuitBreakerMap.containsKey(requestType);
   }
 
   @Override
   public void close() throws IOException {
     synchronized (circuitBreakerMap) {
-      final AtomicInteger closeFailedCounter = new AtomicInteger(0);
-      circuitBreakerMap
-          .values()
-          .forEach(
-              list ->
-                  list.forEach(
-                      it -> {
-                        try {
-                          if (log.isDebugEnabled()) {
-                            log.debug(
-                                "Closed circuit breaker {} for request type(s) 
{}",
-                                it.getClass().getSimpleName(),
-                                it.getRequestTypes());
-                          }
-                          it.close();
-                        } catch (IOException e) {
-                          if (log.isErrorEnabled()) {
-                            log.error(
-                                String.format(
-                                    Locale.ROOT,
-                                    "Failed to close circuit breaker %s",
-                                    it.getClass().getSimpleName()),
-                                e);
-                          }
-                          closeFailedCounter.incrementAndGet();
-                        }
-                      }));
+      closeCircuitBreakers(
+          
circuitBreakerMap.values().stream().flatMap(List::stream).collect(Collectors.toList()));
       circuitBreakerMap.clear();
-      if (closeFailedCounter.get() > 0) {
-        throw new IOException("Failed to close " + closeFailedCounter.get() + 
" circuit breakers");
-      }
     }
   }
+
+  private static void closeGlobal() {
+    synchronized (globalCircuitBreakerMap) {
+      closeCircuitBreakers(
+          globalCircuitBreakerMap.values().stream()
+              .flatMap(List::stream)
+              .collect(Collectors.toList()));
+      globalCircuitBreakerMap.clear();
+    }
+  }
+
+  /**
+   * Close a list of circuit breakers, tracing any failures.
+   *
+   * @throws SolrException if any CB fails to close
+   */
+  private static void closeCircuitBreakers(List<CircuitBreaker> breakers) {
+    final AtomicInteger closeFailedCounter = new AtomicInteger(0);
+    breakers.forEach(
+        it -> {
+          try {
+            if (log.isDebugEnabled()) {
+              log.debug(
+                  "Closed circuit breaker {} for request type(s) {}",

Review Comment:
   ```suggestion
                     "Closing circuit breaker {} for request type(s) {}",
   ```



##########
solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java:
##########
@@ -33,39 +35,47 @@
  * We depend on OperatingSystemMXBean which does not allow a configurable 
interval of collection of
  * data.
  */
-public class CPUCircuitBreaker extends CircuitBreaker {
+public class CPUCircuitBreaker extends CircuitBreaker implements SolrCoreAware 
{
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  private boolean enabled = true;
+  private Boolean enabled = null;
   private double cpuUsageThreshold;
-  private final SolrCore core;
+  private CoreContainer cc;
 
   private static final ThreadLocal<Double> seenCPUUsage = 
ThreadLocal.withInitial(() -> 0.0);
 
   private static final ThreadLocal<Double> allowedCPUUsage = 
ThreadLocal.withInitial(() -> 0.0);
 
-  public CPUCircuitBreaker(SolrCore core) {
+  public CPUCircuitBreaker() {
     super();
-    this.core = core;
+  }
+
+  public CPUCircuitBreaker(CoreContainer coreContainer) {
+    super();
+    this.cc = coreContainer;
   }

Review Comment:
   Wondering if we need to worry about backwards compatibility here, maybe not 
maintaining it but upgrade-note-explaining the signature change perhaps? 
`CircuitBreakerRegistry` is tagged as experimental but this class is not i.e. 
in principle folks could have sub-classed a custom version of it or so.



##########
solr/core/src/java/org/apache/solr/util/circuitbreaker/CPUCircuitBreaker.java:
##########
@@ -33,39 +35,47 @@
  * We depend on OperatingSystemMXBean which does not allow a configurable 
interval of collection of
  * data.
  */
-public class CPUCircuitBreaker extends CircuitBreaker {
+public class CPUCircuitBreaker extends CircuitBreaker implements SolrCoreAware 
{
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  private boolean enabled = true;
+  private Boolean enabled = null;
   private double cpuUsageThreshold;
-  private final SolrCore core;
+  private CoreContainer cc;
 
   private static final ThreadLocal<Double> seenCPUUsage = 
ThreadLocal.withInitial(() -> 0.0);
 
   private static final ThreadLocal<Double> allowedCPUUsage = 
ThreadLocal.withInitial(() -> 0.0);
 
-  public CPUCircuitBreaker(SolrCore core) {
+  public CPUCircuitBreaker() {
     super();
-    this.core = core;
+  }
+
+  public CPUCircuitBreaker(CoreContainer coreContainer) {
+    super();
+    this.cc = coreContainer;
   }
 
   @Override
   public void init(NamedList<?> args) {
     super.init(args);
-    double localSeenCPUUsage = calculateLiveCPUUsage();
-
-    if (localSeenCPUUsage < 0) {
-      String msg =
-          "Initialization failure for CPU circuit breaker. Unable to get 
'systemCpuLoad', not supported by the JVM?";
-      if (log.isErrorEnabled()) {
-        log.error(msg);
-      }
-      enabled = false;
-    }
   }
 
   @Override
   public boolean isTripped() {
+    if (enabled == null) {
+      double localSeenCPUUsage = calculateLiveCPUUsage();
+
+      if (localSeenCPUUsage < 0) {
+        String msg =
+            "Initialization failure for CPU circuit breaker. Unable to get 
'systemCpuLoad', not supported by the JVM?";
+        if (log.isErrorEnabled()) {
+          log.error(msg);
+        }
+        enabled = false;
+      } else {
+        enabled = true;
+      }
+    }

Review Comment:
   Wondering if this could move into the `inform` method to avoid `Boolean` vs. 
`AtomicBoolean` wonderings for `enabled` in case of concurrent `isTripped` 
calls.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org
For additional commands, e-mail: issues-h...@solr.apache.org

Reply via email to