This is an automated email from the ASF dual-hosted git repository.

somandal pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 0dca00766ec Update the UtilizationChecker and 
ResourceUtilizationManager to return an enum instead of boolean (#16255)
0dca00766ec is described below

commit 0dca00766ecc8a5abc8b2fe5c8e036503b19eacb
Author: Sonam Mandal <sonam.man...@startree.ai>
AuthorDate: Wed Jul 2 11:16:57 2025 -0700

    Update the UtilizationChecker and ResourceUtilizationManager to return an 
enum instead of boolean (#16255)
---
 .../helix/core/minion/PinotTaskManager.java        |  8 ++--
 .../validation/DiskUtilizationChecker.java         | 19 ++++++--
 .../RealtimeSegmentValidationManager.java          | 16 +++++--
 .../validation/ResourceUtilizationManager.java     | 28 ++++++++---
 .../controller/validation/UtilizationChecker.java  | 12 ++++-
 .../validation/DiskUtilizationCheckerTest.java     | 56 ++++++++++++++++------
 .../RealtimeSegmentValidationManagerTest.java      | 27 +++++++----
 .../validation/ResourceUtilizationManagerTest.java | 54 +++++++++++++++------
 8 files changed, 163 insertions(+), 57 deletions(-)

diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/minion/PinotTaskManager.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/minion/PinotTaskManager.java
index 96f9154241f..8303eb67f4f 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/minion/PinotTaskManager.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/minion/PinotTaskManager.java
@@ -223,8 +223,8 @@ public class PinotTaskManager extends 
ControllerPeriodicTask<Void> {
       TableConfig tableConfig = 
_pinotHelixResourceManager.getTableConfig(tableNameWithType);
       LOGGER.info("Trying to create tasks of type: {}, table: {}", taskType, 
tableNameWithType);
       try {
-        if 
(!_resourceUtilizationManager.isResourceUtilizationWithinLimits(tableNameWithType,
-            UtilizationChecker.CheckPurpose.TASK_GENERATION)) {
+        if 
(_resourceUtilizationManager.isResourceUtilizationWithinLimits(tableNameWithType,
+            UtilizationChecker.CheckPurpose.TASK_GENERATION) == 
UtilizationChecker.CheckResult.FAIL) {
           LOGGER.warn("Resource utilization is above threshold, skipping task 
creation for table: {}", tableName);
           _controllerMetrics.setOrUpdateTableGauge(tableName, 
ControllerGauge.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 1L);
           continue;
@@ -723,8 +723,8 @@ public class PinotTaskManager extends 
ControllerPeriodicTask<Void> {
     for (TableConfig tableConfig : enabledTableConfigs) {
       String tableName = tableConfig.getTableName();
       try {
-        if 
(!_resourceUtilizationManager.isResourceUtilizationWithinLimits(tableName,
-            UtilizationChecker.CheckPurpose.TASK_GENERATION)) {
+        if 
(_resourceUtilizationManager.isResourceUtilizationWithinLimits(tableName,
+            UtilizationChecker.CheckPurpose.TASK_GENERATION) == 
UtilizationChecker.CheckResult.FAIL) {
           String message = String.format("Skipping tasks generation as 
resource utilization is not within limits for "
               + "table: %s. Disk utilization for one or more servers hosting 
this table has exceeded the threshold. "
               + "Tasks won't be generated until the issue is mitigated.", 
tableName);
diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/DiskUtilizationChecker.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/DiskUtilizationChecker.java
index fa2f1bfbea2..45616227b85 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/DiskUtilizationChecker.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/DiskUtilizationChecker.java
@@ -63,14 +63,14 @@ public class DiskUtilizationChecker implements 
UtilizationChecker {
    * Check if disk utilization for the requested table is within the 
configured limits.
    */
   @Override
-  public boolean isResourceUtilizationWithinLimits(String tableNameWithType, 
UtilizationChecker.CheckPurpose purpose) {
+  public CheckResult isResourceUtilizationWithinLimits(String 
tableNameWithType, CheckPurpose purpose) {
     if (StringUtils.isEmpty(tableNameWithType)) {
       throw new IllegalArgumentException("Table name found to be null or empty 
while computing disk utilization.");
     }
     TableConfig tableConfig = 
_helixResourceManager.getTableConfig(tableNameWithType);
     if (tableConfig == null) {
       LOGGER.warn("Table config for table: {} is null", tableNameWithType);
-      return true; // table does not exist
+      return CheckResult.PASS; // table does not exist
     }
     List<String> instances;
     if (TableNameBuilder.isOfflineTableResource(tableNameWithType)) {
@@ -81,10 +81,12 @@ public class DiskUtilizationChecker implements 
UtilizationChecker {
     return isDiskUtilizationWithinLimits(instances);
   }
 
-  private boolean isDiskUtilizationWithinLimits(List<String> instances) {
+  private CheckResult isDiskUtilizationWithinLimits(List<String> instances) {
+    int numInstancesWithStaleOrNullResults = 0;
     for (String instance : instances) {
       DiskUsageInfo diskUsageInfo = 
ResourceUtilizationInfo.getDiskUsageInfo(instance);
       if (diskUsageInfo == null) {
+        numInstancesWithStaleOrNullResults++;
         LOGGER.warn("Disk utilization info for server: {} is null", instance);
         continue;
       }
@@ -92,6 +94,7 @@ public class DiskUtilizationChecker implements 
UtilizationChecker {
       // ResourceUtilizationChecker tasks frequency.
       if (diskUsageInfo.getLastUpdatedTimeInEpochMs()
           < System.currentTimeMillis() - 
_resourceUtilizationCheckerFrequencyMs) {
+        numInstancesWithStaleOrNullResults++;
         LOGGER.warn("Disk utilization info for server: {} is stale", instance);
         continue;
       }
@@ -99,10 +102,16 @@ public class DiskUtilizationChecker implements 
UtilizationChecker {
         LOGGER.warn("Disk utilization for server: {} is above threshold: {}%. 
UsedBytes: {}, TotalBytes: {}",
             instance, diskUsageInfo.getUsedSpaceBytes() * 100 / 
diskUsageInfo.getTotalSpaceBytes(), diskUsageInfo
                 .getUsedSpaceBytes(), diskUsageInfo.getTotalSpaceBytes());
-        return false;
+        return CheckResult.FAIL;
       }
     }
-    return true;
+    // If results for all servers is null or stale, return the status as STALE 
to indicate that the status cannot be
+    // determined.
+    // TODO: Have better handling for partial STALE results from servers. It 
is possible that a subset of servers are
+    //       STALE, and these are the ones that may have a resource 
utilization breach, but we return TRUE here.
+    //       Eventually when the status is updated, the correct value will be 
returned and the correct action can be
+    //       taken based on that. Temporarily the action taken may be the 
wrong one.
+    return numInstancesWithStaleOrNullResults == instances.size() ? 
CheckResult.UNDETERMINED : CheckResult.PASS;
   }
 
   /**
diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManager.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManager.java
index 39cf6f1b75f..d5ac06062c3 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManager.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManager.java
@@ -156,10 +156,10 @@ public class RealtimeSegmentValidationManager extends 
ControllerPeriodicTask<Rea
       return false; // if table is paused by admin, then skip subsequent checks
     }
     // Perform resource utilization checks.
-    boolean isResourceUtilizationWithinLimits =
+    UtilizationChecker.CheckResult isResourceUtilizationWithinLimits =
         
_resourceUtilizationManager.isResourceUtilizationWithinLimits(tableNameWithType,
             UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    if (!isResourceUtilizationWithinLimits) {
+    if (isResourceUtilizationWithinLimits == 
UtilizationChecker.CheckResult.FAIL) {
       LOGGER.warn("Resource utilization limit exceeded for table: {}", 
tableNameWithType);
       _controllerMetrics.setOrUpdateTableGauge(tableNameWithType, 
ControllerGauge.RESOURCE_UTILIZATION_LIMIT_EXCEEDED,
           1L);
@@ -170,14 +170,22 @@ public class RealtimeSegmentValidationManager extends 
ControllerPeriodicTask<Rea
             PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
"Resource utilization limit exceeded.");
       }
       return false; // if resource utilization check failed, then skip 
subsequent checks
+    } else if ((isResourceUtilizationWithinLimits == 
UtilizationChecker.CheckResult.PASS) && isTablePaused
+        && 
pauseStatus.getReasonCode().equals(PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED))
 {
       // within limits and table previously paused by resource utilization --> 
unpause
-    } else if (isTablePaused && pauseStatus.getReasonCode()
-        .equals(PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED)) {
+      LOGGER.info("Resource utilization limit is back within limits for table: 
{}", tableNameWithType);
       // unset the pause state and allow consuming segment recreation.
       
_llcRealtimeSegmentManager.updatePauseStateInIdealState(tableNameWithType, 
false,
           PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, "Resource 
utilization within limits");
       pauseStatus = 
_llcRealtimeSegmentManager.getPauseStatusDetails(tableNameWithType);
       isTablePaused = pauseStatus.getPauseFlag();
+    } else if ((isResourceUtilizationWithinLimits == 
UtilizationChecker.CheckResult.UNDETERMINED) && isTablePaused
+        && 
pauseStatus.getReasonCode().equals(PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED))
 {
+      // The table was previously paused due to exceeding resource 
utilization, but the current status cannot be
+      // determined. To be safe, leave it as paused and once the status is 
available take the correct action
+      LOGGER.warn("Resource utilization limit could not be determined for for 
table: {}, and it is paused, leave it as "
+              + "paused", tableNameWithType);
+      return false;
     }
     _controllerMetrics.setOrUpdateTableGauge(tableNameWithType, 
ControllerGauge.RESOURCE_UTILIZATION_LIMIT_EXCEEDED,
         0L);
diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/ResourceUtilizationManager.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/ResourceUtilizationManager.java
index 396d6ba68c4..cda90ed71eb 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/ResourceUtilizationManager.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/ResourceUtilizationManager.java
@@ -38,22 +38,38 @@ public class ResourceUtilizationManager {
     _utilizationCheckers = utilizationCheckers;
   }
 
-  public boolean isResourceUtilizationWithinLimits(String tableNameWithType, 
UtilizationChecker.CheckPurpose purpose) {
+  /**
+   * Returns the status of the resource utilization check across all 
UtilizationCheckers
+   * @param tableNameWithType table name with type
+   * @param purpose the purpose of the utilization check
+   * @return CheckResult, FAIL if even one resource utilization checker has 
returned FALSE, UNDETERMINED if the result
+   *         cannot be determined for even one UtilizationChecker and all the 
others are also UNDETERMINED or PASS,
+   *         and PASS if resource utilization is within limits for all 
UtilizationCheckers
+   */
+  public UtilizationChecker.CheckResult 
isResourceUtilizationWithinLimits(String tableNameWithType,
+      UtilizationChecker.CheckPurpose purpose) {
     if (!_isResourceUtilizationCheckEnabled) {
-      return true;
+      return UtilizationChecker.CheckResult.PASS;
     }
     if (StringUtils.isEmpty(tableNameWithType)) {
       throw new IllegalArgumentException("Table name found to be null or empty 
while checking resource utilization.");
     }
     LOGGER.info("Checking resource utilization for table: {}", 
tableNameWithType);
-    boolean overallIsResourceUtilizationWithinLimits = true;
+    UtilizationChecker.CheckResult overallIsResourceUtilizationWithinLimits = 
UtilizationChecker.CheckResult.PASS;
     for (UtilizationChecker utilizationChecker : _utilizationCheckers) {
-      boolean isResourceUtilizationWithinLimits =
+      UtilizationChecker.CheckResult isResourceUtilizationWithinLimits =
           
utilizationChecker.isResourceUtilizationWithinLimits(tableNameWithType, 
purpose);
       LOGGER.info("For utilization checker: {}, 
isResourceUtilizationWithinLimits: {}, purpose: {}",
           utilizationChecker.getName(), isResourceUtilizationWithinLimits, 
purpose);
-      if (!isResourceUtilizationWithinLimits) {
-        overallIsResourceUtilizationWithinLimits = false;
+      if (isResourceUtilizationWithinLimits == 
UtilizationChecker.CheckResult.FAIL) {
+        // If any UtilizationChecker returns FAIL, we should mark the overall 
as FAIL. FAIL should always have
+        // priority over other results
+        overallIsResourceUtilizationWithinLimits = 
UtilizationChecker.CheckResult.FAIL;
+      } else if ((overallIsResourceUtilizationWithinLimits == 
UtilizationChecker.CheckResult.PASS)
+          && (isResourceUtilizationWithinLimits == 
UtilizationChecker.CheckResult.UNDETERMINED)) {
+        // If we haven't already updated the overall to a value other than 
PASS, and we get an UNDETERMINED result,
+        // update the overall to UNDETERMINED. Should not update to 
UNDETERMINED if we have set the overall to FAIL
+        overallIsResourceUtilizationWithinLimits = 
UtilizationChecker.CheckResult.UNDETERMINED;
       }
     }
     return overallIsResourceUtilizationWithinLimits;
diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/UtilizationChecker.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/UtilizationChecker.java
index 2a4cdc9ce19..7b122bb98f1 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/validation/UtilizationChecker.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/validation/UtilizationChecker.java
@@ -32,11 +32,12 @@ public interface UtilizationChecker {
   String getName();
 
   /**
-   * Returns true if the resource's utilization is within limits
+   * Returns whether the resource's utilization is within limits
    * @param tableNameWithType table name with type
    * @param purpose purpose of this check
+   * @return CheckResult, UNDETERMINED if result cannot be determined, PASS if 
within limits, FAIL if not within limits
    */
-  boolean isResourceUtilizationWithinLimits(String tableNameWithType, 
CheckPurpose purpose);
+  CheckResult isResourceUtilizationWithinLimits(String tableNameWithType, 
CheckPurpose purpose);
 
   /**
    * Computes the resource's utilization
@@ -55,4 +56,11 @@ public interface UtilizationChecker {
     // TASK_GENERATION if the check is performed from the task generation 
framework to pause creation of new tasks
     REALTIME_INGESTION, TASK_GENERATION
   }
+
+  enum CheckResult {
+    // PASS if the resource's utilization is within limits
+    // FAIL if the resource's utilization is not within limits
+    // UNDETERMINED if the result cannot be determined due to not having 
sufficient information
+    PASS, FAIL, UNDETERMINED
+  }
 }
diff --git 
a/pinot-controller/src/test/java/org/apache/pinot/controller/validation/DiskUtilizationCheckerTest.java
 
b/pinot-controller/src/test/java/org/apache/pinot/controller/validation/DiskUtilizationCheckerTest.java
index 3e29c0c57f7..4643fc7aa04 100644
--- 
a/pinot-controller/src/test/java/org/apache/pinot/controller/validation/DiskUtilizationCheckerTest.java
+++ 
b/pinot-controller/src/test/java/org/apache/pinot/controller/validation/DiskUtilizationCheckerTest.java
@@ -80,27 +80,55 @@ public class DiskUtilizationCheckerTest {
     String tableName = "test_OFFLINE";
     
when(_helixResourceManager.getOfflineTableConfig(tableName)).thenReturn(null);
 
-    boolean result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
+    UtilizationChecker.CheckResult result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertTrue(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS);
 
     result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertTrue(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS);
   }
 
   @Test
   public void testIsDiskUtilizationWithinLimitsNonExistentRealtimeTable() {
     String tableName = "test_REALTIME";
-    
when(_helixResourceManager.getRealtimeTableConfig(tableName)).thenReturn(null);
+    when(_helixResourceManager.getTableConfig(tableName)).thenReturn(null);
 
-    boolean result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
+    UtilizationChecker.CheckResult result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertTrue(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS);
 
     result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertTrue(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS);
+  }
+
+  @Test
+  public void testIsDiskUtilizationStale() {
+    String tableName = "test_OFFLINE";
+
+    TableConfig mockTableConfig = mock(TableConfig.class);
+    
when(_helixResourceManager.getTableConfig(tableName)).thenReturn(mockTableConfig);
+
+    List<String> mockInstances = Arrays.asList("server1", "server2");
+    when(_helixResourceManager.getServerInstancesForTable(tableName, 
TableType.OFFLINE)).thenReturn(mockInstances);
+
+    // Mock disk usage
+    Map<String, DiskUsageInfo> diskUsageInfoMap = new HashMap<>();
+    DiskUsageInfo diskUsageInfo1 = new DiskUsageInfo("server1");
+    diskUsageInfoMap.put("server1", diskUsageInfo1);
+
+    DiskUsageInfo diskUsageInfo2 = new DiskUsageInfo("server2");
+    diskUsageInfoMap.put("server2", diskUsageInfo2);
+    ResourceUtilizationInfo.setDiskUsageInfo(diskUsageInfoMap);
+
+    UtilizationChecker.CheckResult result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
+        UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.UNDETERMINED);
+
+    result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
+        UtilizationChecker.CheckPurpose.TASK_GENERATION);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.UNDETERMINED);
   }
 
   @Test
@@ -108,7 +136,7 @@ public class DiskUtilizationCheckerTest {
     String tableName = "test_OFFLINE";
 
     TableConfig mockTableConfig = mock(TableConfig.class);
-    
when(_helixResourceManager.getOfflineTableConfig(tableName)).thenReturn(mockTableConfig);
+    
when(_helixResourceManager.getTableConfig(tableName)).thenReturn(mockTableConfig);
 
     List<String> mockInstances = Arrays.asList("server1", "server2");
     when(_helixResourceManager.getServerInstancesForTable(tableName, 
TableType.OFFLINE)).thenReturn(mockInstances);
@@ -124,13 +152,13 @@ public class DiskUtilizationCheckerTest {
     diskUsageInfoMap.put("server2", diskUsageInfo2);
     ResourceUtilizationInfo.setDiskUsageInfo(diskUsageInfoMap);
 
-    boolean result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
+    UtilizationChecker.CheckResult result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertTrue(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS);
 
     result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertTrue(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS);
   }
 
   @Test
@@ -154,13 +182,13 @@ public class DiskUtilizationCheckerTest {
     diskUsageInfoMap.put("server2", diskUsageInfo2);
     ResourceUtilizationInfo.setDiskUsageInfo(diskUsageInfoMap);
 
-    boolean result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
+    UtilizationChecker.CheckResult result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertFalse(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.FAIL);
 
     result = 
_diskUtilizationChecker.isResourceUtilizationWithinLimits(tableName,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertFalse(result);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.FAIL);
   }
 
   @Test
diff --git 
a/pinot-controller/src/test/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManagerTest.java
 
b/pinot-controller/src/test/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManagerTest.java
index 9c435a48e88..4c74c0bc1f3 100644
--- 
a/pinot-controller/src/test/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManagerTest.java
+++ 
b/pinot-controller/src/test/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManagerTest.java
@@ -74,29 +74,40 @@ public class RealtimeSegmentValidationManagerTest {
   public Object[][] testCases() {
     return new Object[][]{
         // Table is paused due to admin intervention, should return false
-        {true, PauseState.ReasonCode.ADMINISTRATIVE, false, false, false},
+        {true, PauseState.ReasonCode.ADMINISTRATIVE, 
UtilizationChecker.CheckResult.PASS, false, false},
 
         // Resource utilization exceeded and pause state is updated, should 
return false
-        {false, PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
true, false, false},
+        {false, PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
UtilizationChecker.CheckResult.FAIL, false,
+            false},
 
         // Resource utilization is within limits but was previously paused due 
to resource utilization,
         // should return true
-        {true, PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
false, false, true},
+        {true, PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
UtilizationChecker.CheckResult.PASS, false,
+            true},
+
+        // Resource utilization is STALE but was previously paused due to 
resource utilization, should return false
+        {true, PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
UtilizationChecker.CheckResult.UNDETERMINED,
+            false, false},
+
+        // Resource utilization is STALE but was not previously paused due to 
resource utilization, should return true
+        {false, PauseState.ReasonCode.RESOURCE_UTILIZATION_LIMIT_EXCEEDED, 
UtilizationChecker.CheckResult.UNDETERMINED,
+            false, true},
 
         // Resource utilization is within limits but was previously paused due 
to storage quota exceeded,
         // should return false
-        {true, PauseState.ReasonCode.STORAGE_QUOTA_EXCEEDED, false, true, 
false},
+        {true, PauseState.ReasonCode.STORAGE_QUOTA_EXCEEDED, 
UtilizationChecker.CheckResult.PASS, true, false},
 
         // Storage quota exceeded, should return false
-        {false, PauseState.ReasonCode.STORAGE_QUOTA_EXCEEDED, false, true, 
false},
+        {false, PauseState.ReasonCode.STORAGE_QUOTA_EXCEEDED, 
UtilizationChecker.CheckResult.PASS, true, false},
 
         // Storage quota within limits but was previously paused due to 
storage quota exceeded, should return true
-        {true, PauseState.ReasonCode.STORAGE_QUOTA_EXCEEDED, false, false, 
true}};
+        {true, PauseState.ReasonCode.STORAGE_QUOTA_EXCEEDED, 
UtilizationChecker.CheckResult.PASS, false, true}};
   }
 
   @Test(dataProvider = "testCases")
   public void testShouldEnsureConsuming(boolean isTablePaused, 
PauseState.ReasonCode reasonCode,
-      boolean isResourceUtilizationExceeded, boolean isQuotaExceeded, boolean 
expectedResult) {
+      UtilizationChecker.CheckResult isResourceUtilizationWithinLimits, 
boolean isQuotaExceeded,
+      boolean expectedResult) {
     String tableName = "testTable_REALTIME";
     PauseStatusDetails pauseStatus = mock(PauseStatusDetails.class);
     TableConfig tableConfig = mock(TableConfig.class);
@@ -105,7 +116,7 @@ public class RealtimeSegmentValidationManagerTest {
     when(pauseStatus.getReasonCode()).thenReturn(reasonCode);
     
when(_llcRealtimeSegmentManager.getPauseStatusDetails(tableName)).thenReturn(pauseStatus);
     
when(_resourceUtilizationManager.isResourceUtilizationWithinLimits(tableName,
-        
UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(!isResourceUtilizationExceeded);
+        
UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(isResourceUtilizationWithinLimits);
     
when(_pinotHelixResourceManager.getTableConfig(tableName)).thenReturn(tableConfig);
     
when(_storageQuotaChecker.isTableStorageQuotaExceeded(tableConfig)).thenReturn(isQuotaExceeded);
 
diff --git 
a/pinot-controller/src/test/java/org/apache/pinot/controller/validation/ResourceUtilizationManagerTest.java
 
b/pinot-controller/src/test/java/org/apache/pinot/controller/validation/ResourceUtilizationManagerTest.java
index 9487105d530..a371d5dff40 100644
--- 
a/pinot-controller/src/test/java/org/apache/pinot/controller/validation/ResourceUtilizationManagerTest.java
+++ 
b/pinot-controller/src/test/java/org/apache/pinot/controller/validation/ResourceUtilizationManagerTest.java
@@ -46,13 +46,15 @@ public class ResourceUtilizationManagerTest {
     
Mockito.when(_controllerConf.isResourceUtilizationCheckEnabled()).thenReturn(false);
     _resourceUtilizationManager = new 
ResourceUtilizationManager(_controllerConf, _utilizationCheckers);
 
-    boolean result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
+    UtilizationChecker.CheckResult result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertTrue(result, "Resource utilization should be within limits 
when the check is disabled");
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS,
+        "Resource utilization should be within limits when the check is 
disabled");
 
     result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertTrue(result, "Resource utilization should be within limits 
when the check is disabled");
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS,
+        "Resource utilization should be within limits when the check is 
disabled");
   }
 
   @Test(expectedExceptions = IllegalArgumentException.class)
@@ -95,35 +97,59 @@ public class ResourceUtilizationManagerTest {
   public void testIsResourceUtilizationWithinLimitsWhenCheckIsEnabled() {
     
Mockito.when(_controllerConf.isResourceUtilizationCheckEnabled()).thenReturn(true);
     
Mockito.when(_diskUtilizationChecker.isResourceUtilizationWithinLimits(_testTable,
-        UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(true);
+        
UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(UtilizationChecker.CheckResult.PASS);
     _resourceUtilizationManager = new 
ResourceUtilizationManager(_controllerConf, _utilizationCheckers);
 
-    boolean result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
+    UtilizationChecker.CheckResult result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertTrue(result, "Resource utilization should be within limits 
when disk check and primary key count "
-        + "check returns true");
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS,
+        "Resource utilization should be within limits when disk check and 
primary key count check returns true");
 
     
Mockito.when(_diskUtilizationChecker.isResourceUtilizationWithinLimits(_testTable,
-        UtilizationChecker.CheckPurpose.TASK_GENERATION)).thenReturn(true);
+        
UtilizationChecker.CheckPurpose.TASK_GENERATION)).thenReturn(UtilizationChecker.CheckResult.PASS);
     result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertTrue(result, "Resource utilization should be within limits 
when disk check and primary key count "
-        + "check returns true");
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.PASS,
+        "Resource utilization should be within limits when disk check and 
primary key count check returns true");
   }
 
   @Test
   public void testIsResourceUtilizationWithinLimitsWhenCheckFails() {
     
Mockito.when(_controllerConf.isResourceUtilizationCheckEnabled()).thenReturn(true);
     
Mockito.when(_diskUtilizationChecker.isResourceUtilizationWithinLimits(_testTable,
-        UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(false);
+        
UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(UtilizationChecker.CheckResult.FAIL);
+    
Mockito.when(_diskUtilizationChecker.isResourceUtilizationWithinLimits(_testTable,
+        
UtilizationChecker.CheckPurpose.TASK_GENERATION)).thenReturn(UtilizationChecker.CheckResult.FAIL);
+    _resourceUtilizationManager = new 
ResourceUtilizationManager(_controllerConf, _utilizationCheckers);
+
+    UtilizationChecker.CheckResult result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
+        UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.FAIL,
+        "Resource utilization should not be within limits when disk check 
returns false");
+
+    result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
+        UtilizationChecker.CheckPurpose.TASK_GENERATION);
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.FAIL,
+        "Resource utilization should not be within limits when disk check 
returns false");
+  }
+
+  @Test
+  public void testIsResourceUtilizationWithinLimitsWhenCheckStale() {
+    
Mockito.when(_controllerConf.isResourceUtilizationCheckEnabled()).thenReturn(true);
+    
Mockito.when(_diskUtilizationChecker.isResourceUtilizationWithinLimits(_testTable,
+        
UtilizationChecker.CheckPurpose.REALTIME_INGESTION)).thenReturn(UtilizationChecker.CheckResult.UNDETERMINED);
+    
Mockito.when(_diskUtilizationChecker.isResourceUtilizationWithinLimits(_testTable,
+        
UtilizationChecker.CheckPurpose.TASK_GENERATION)).thenReturn(UtilizationChecker.CheckResult.UNDETERMINED);
     _resourceUtilizationManager = new 
ResourceUtilizationManager(_controllerConf, _utilizationCheckers);
 
-    boolean result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
+    UtilizationChecker.CheckResult result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
         UtilizationChecker.CheckPurpose.REALTIME_INGESTION);
-    Assert.assertFalse(result, "Resource utilization should not be within 
limits when disk check returns false");
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.UNDETERMINED,
+        "Resource utilization should return STALE when the diskUtilization 
returns STALE");
 
     result = 
_resourceUtilizationManager.isResourceUtilizationWithinLimits(_testTable,
         UtilizationChecker.CheckPurpose.TASK_GENERATION);
-    Assert.assertFalse(result, "Resource utilization should not be within 
limits when disk check returns false");
+    Assert.assertEquals(result, UtilizationChecker.CheckResult.UNDETERMINED,
+        "Resource utilization should return STALE when the diskUtilization 
returns STALE");
   }
 }


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

Reply via email to