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

jackie 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 078117e67e Fix bug when evaluating resource status during service 
startup check (#13541)
078117e67e is described below

commit 078117e67ef8da454850791c4ebbbb2bdf37998c
Author: Christopher Peck <[email protected]>
AuthorDate: Tue Aug 6 14:08:30 2024 -0700

    Fix bug when evaluating resource status during service startup check 
(#13541)
---
 .../apache/pinot/common/utils/ServiceStatus.java   | 25 +++++++++++++++--
 .../pinot/common/utils/ServiceStatusTest.java      | 31 +++++++++++++++++++---
 2 files changed, 51 insertions(+), 5 deletions(-)

diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/ServiceStatus.java 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/ServiceStatus.java
index 21ebd1fe21..3731d3b23d 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/ServiceStatus.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/ServiceStatus.java
@@ -434,6 +434,26 @@ public class ServiceStatus {
         return new StatusDescriptionPair(Status.GOOD, STATUS_DESCRIPTION_NONE);
       }
 
+      // Get ideal state partitions for all instances
+      Map<String, Map<String, String>> idealStateMapFields = 
idealState.getRecord().getMapFields();
+      if (idealStateMapFields == null || idealStateMapFields.isEmpty()) {
+        return new StatusDescriptionPair(Status.GOOD, 
STATUS_DESCRIPTION_NONE); // Resource has no partitions
+      }
+
+      // Collect all partitions that are assigned to this instance
+      Map<String, String> instanceStateMap = new HashMap<>();
+      for (Map.Entry<String, Map<String, String>> partition : 
idealStateMapFields.entrySet()) {
+        if (partition.getValue().containsKey(_instanceName)) {
+          instanceStateMap.put(partition.getKey(), 
partition.getValue().get(_instanceName));
+        }
+      }
+
+      // Resource has no partitions assigned to this instance, so the resource 
status is GOOD
+      if (instanceStateMap.isEmpty()) {
+        return new StatusDescriptionPair(Status.GOOD, STATUS_DESCRIPTION_NONE);
+      }
+
+      // Null EV or CS, when resource has assigned partitions, means that the 
service status is STARTING
       T helixState = getState(resourceName);
       if (helixState == null) {
         return new StatusDescriptionPair(Status.STARTING, 
STATUS_DESCRIPTION_NO_HELIX_STATE);
@@ -443,8 +463,9 @@ public class ServiceStatus {
       // external view or went to ERROR state (which means that we tried to 
load the segments/resources but failed for
       // some reason)
       Map<String, String> partitionStateMap = getPartitionStateMap(helixState);
-      for (String partitionName : idealState.getPartitionSet()) {
-        String idealStateStatus = 
idealState.getInstanceStateMap(partitionName).get(_instanceName);
+      for (Map.Entry<String, String> entry : instanceStateMap.entrySet()) {
+        String partitionName = entry.getKey();
+        String idealStateStatus = entry.getValue();
 
         // Skip this partition if it is not assigned to this instance or if 
the instance should be offline
         if (idealStateStatus == null || "OFFLINE".equals(idealStateStatus)) {
diff --git 
a/pinot-common/src/test/java/org/apache/pinot/common/utils/ServiceStatusTest.java
 
b/pinot-common/src/test/java/org/apache/pinot/common/utils/ServiceStatusTest.java
index a214f17f51..1c9c939e08 100644
--- 
a/pinot-common/src/test/java/org/apache/pinot/common/utils/ServiceStatusTest.java
+++ 
b/pinot-common/src/test/java/org/apache/pinot/common/utils/ServiceStatusTest.java
@@ -28,6 +28,7 @@ import java.util.Random;
 import org.apache.helix.HelixManager;
 import org.apache.helix.model.ExternalView;
 import org.apache.helix.model.IdealState;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
 import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
@@ -134,9 +135,33 @@ public class ServiceStatusTest {
     callback.setExternalView(new ExternalView(TABLE_NAME));
     assertEquals(callback.getServiceStatus(), ServiceStatus.Status.GOOD);
 
-    // No external view = STARTING
+    // No external view, and ideal state shows this instance is assigned a 
segment of the resource = STARTING
     callback = buildTestISEVCallback();
-    callback.setIdealState(new IdealState(TABLE_NAME));
+    ZNRecord znRecord = new ZNRecord(TABLE_NAME);
+    znRecord.setSimpleField("REBALANCE_MODE", "CUSTOMIZED");
+    znRecord.setMapField("segment1", Map.of(INSTANCE_NAME, "ONLINE"));
+    callback.setIdealState(new IdealState(znRecord));
+    assertEquals(callback.getServiceStatus(), ServiceStatus.Status.STARTING);
+
+    // No external view, and ideal state shows this instance is not assigned a 
segment of the resource = GOOD
+    callback = buildTestISEVCallback();
+    znRecord = new ZNRecord(TABLE_NAME);
+    znRecord.setSimpleField("REBALANCE_MODE", "CUSTOMIZED");
+    znRecord.setMapField("segment1", Map.of("otherServerInstance", "ONLINE"));
+    callback.setIdealState(new IdealState(znRecord));
+    assertEquals(callback.getServiceStatus(), ServiceStatus.Status.GOOD);
+
+    // Online ideal state, and external view shows second segment is still 
offline = STARTING
+    callback = buildTestISEVCallback();
+    znRecord = new ZNRecord(TABLE_NAME);
+    znRecord.setSimpleField("REBALANCE_MODE", "CUSTOMIZED");
+    znRecord.setMapField("segment1", Map.of(INSTANCE_NAME, "ONLINE"));
+    znRecord.setMapField("segment2", Map.of(INSTANCE_NAME, "ONLINE"));
+    callback.setIdealState(new IdealState(znRecord));
+    ExternalView externalView = new ExternalView(TABLE_NAME);
+    externalView.setState("segment1", INSTANCE_NAME, "ONLINE");
+    externalView.setState("segment2", INSTANCE_NAME, "OFFLINE");
+    callback.setExternalView(externalView);
     assertEquals(callback.getServiceStatus(), ServiceStatus.Status.STARTING);
 
     // Empty ideal state + empty external view = GOOD
@@ -170,7 +195,7 @@ public class ServiceStatusTest {
     idealState.setPartitionState("mySegment_1", INSTANCE_NAME, "ONLINE");
     idealState.setPartitionState("mySegment_2", INSTANCE_NAME, "OFFLINE");
     callback.setIdealState(idealState);
-    ExternalView externalView = new ExternalView(TABLE_NAME);
+    externalView = new ExternalView(TABLE_NAME);
     externalView.setState("mySegment_1", INSTANCE_NAME, "ONLINE");
     callback.setExternalView(externalView);
     assertEquals(callback.getServiceStatus(), ServiceStatus.Status.GOOD);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to