diff --git a/hugegraph-pd/hg-pd-service/src/main/java/org/apache/hugegraph/pd/rest/IndexAPI.java b/hugegraph-pd/hg-pd-service/src/main/java/org/apache/hugegraph/pd/rest/IndexAPI.java index a0448965f1..bee39f23ed 100644 --- a/hugegraph-pd/hg-pd-service/src/main/java/org/apache/hugegraph/pd/rest/IndexAPI.java +++ b/hugegraph-pd/hg-pd-service/src/main/java/org/apache/hugegraph/pd/rest/IndexAPI.java @@ -66,9 +66,35 @@ public BriefStatistics index() throws PDException, ExecutionException, Interrupt BriefStatistics statistics = new BriefStatistics(); statistics.leader = RaftEngine.getInstance().getLeaderGrpcAddress(); statistics.state = pdService.getStoreNodeService().getClusterStats().getState().toString(); + + // Use pdService (consistent with cluster()) rather than RaftEngine directly + CallStreamObserverWrap membersResp = + new CallStreamObserverWrap<>(); + pdService.getMembers(Pdpb.GetMembersRequest.newBuilder().build(), membersResp); + statistics.memberSize = membersResp.get().get(0).getMembersList().size(); + statistics.storeSize = pdService.getStoreNodeService().getActiveStores().size(); - statistics.graphSize = pdService.getPartitionService().getGraphs().size(); + // Filter to user-facing graphs only (consistent with cluster()) + List graphs = pdRestService.getGraphs(); + statistics.graphSize = (int) graphs.stream() + .filter(g -> g.getGraphName() != null && + g.getGraphName().endsWith("/g")) + .count(); statistics.partitionSize = pdService.getStoreNodeService().getShardGroups().size(); + + // Derive worst partition health state across all graphs + Metapb.PartitionState dataState = Metapb.PartitionState.PState_Normal; + for (Metapb.Graph graph : graphs) { + if (graph.getState() == Metapb.PartitionState.UNRECOGNIZED) { + continue; + } + if (graph.getState() != null && + graph.getState().getNumber() > dataState.getNumber()) { + dataState = graph.getState(); + } + } + statistics.dataState = dataState.name(); + return statistics; } @@ -157,9 +183,13 @@ public RestApiResponse cluster() throws InterruptedException, ExecutionException class BriefStatistics { String state; + /** Worst partition health state across all graphs (mirrors cluster().dataState) */ + String dataState; String leader; int memberSize; + /** Active (online) store count only */ int storeSize; + /** User-facing graphs count (graphName ending with /g) */ int graphSize; int partitionSize; } diff --git a/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/rest/RestApiTest.java b/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/rest/RestApiTest.java index 2d6f4f054b..fb2b71d480 100644 --- a/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/rest/RestApiTest.java +++ b/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/rest/RestApiTest.java @@ -29,6 +29,25 @@ public class RestApiTest extends BaseServerTest { + @Test + public void testQueryIndexInfo() throws URISyntaxException, IOException, InterruptedException, + JSONException { + String url = pdRestAddr + "/"; + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(url)) + .header("Authorization", "Basic c3RvcmU6MTIz") + .GET() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assert response.statusCode() == 200; + JSONObject obj = new JSONObject(response.body()); + assert obj.getString("state") != null; + assert obj.getString("leader") != null; + assert obj.getInt("memberSize") > 0 : "memberSize should be > 0 for a running cluster"; + // storeSize can be 0 in PD-only test environments with no store nodes registered + assert obj.getInt("storeSize") >= 0; + } + @Test public void testQueryClusterInfo() throws URISyntaxException, IOException, InterruptedException, JSONException { diff --git a/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/service/RestApiTest.java b/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/service/RestApiTest.java index d4c9cd121e..b899c09194 100644 --- a/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/service/RestApiTest.java +++ b/hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/service/RestApiTest.java @@ -29,6 +29,24 @@ public class RestApiTest extends BaseServerTest { + @Test + public void testQueryIndexInfo() throws URISyntaxException, IOException, InterruptedException, + JSONException { + String url = pdRestAddr + "/"; + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(url)).header(key, value) + .GET() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assert response.statusCode() == 200; + JSONObject obj = new JSONObject(response.body()); + assert obj.getString("state") != null; + assert obj.getString("leader") != null; + assert obj.getInt("memberSize") > 0 : "memberSize should be > 0 for a running cluster"; + // storeSize can be 0 in PD-only test environments with no store nodes registered + assert obj.getInt("storeSize") >= 0; + } + @Test public void testQueryClusterInfo() throws URISyntaxException, IOException, InterruptedException, JSONException {