From 27b727a358a362d772444ce64ce97c06374de4e3 Mon Sep 17 00:00:00 2001 From: hutiefang Date: Sun, 21 Jun 2026 10:54:56 +0800 Subject: [PATCH 1/7] fix: support new HugeGraph edge id format --- .../computer/core/input/HugeConverter.java | 20 +++++++++++++++++++ .../core/worker/load/LoadService.java | 3 ++- .../core/input/HugeConverterTest.java | 19 ++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java index dd94dabc5..c8153e88c 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java @@ -36,7 +36,9 @@ import org.apache.hugegraph.computer.core.graph.value.NullValue; import org.apache.hugegraph.computer.core.graph.value.StringValue; import org.apache.hugegraph.computer.core.graph.value.Value; +import org.apache.hugegraph.structure.graph.Edge; import org.apache.hugegraph.util.E; +import org.apache.hugegraph.util.SplicingIdGenerator; public final class HugeConverter { @@ -96,4 +98,22 @@ public static Properties convertProperties( } return properties; } + + public static String convertEdgeName(Edge edge) { + E.checkArgumentNotNull(edge, "The edge can't be null"); + String edgeId = edge.id(); + if (edgeId == null) { + return edge.name(); + } + + String[] parts = SplicingIdGenerator.split(edgeId); + if (parts.length == 4) { + return parts[2]; + } else if (parts.length == 5) { + return parts[3]; + } else if (parts.length == 6) { + return parts[4]; + } + return edge.name(); + } } diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/worker/load/LoadService.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/worker/load/LoadService.java index 237b02d5e..2b4af436c 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/worker/load/LoadService.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/worker/load/LoadService.java @@ -238,7 +238,8 @@ private Edge convert(org.apache.hugegraph.structure.graph.Edge edge) { Properties properties = HugeConverter.convertProperties( edge.properties()); Edge computerEdge = graphFactory.createEdge(edge.label(), - edge.name(), targetId + HugeConverter.convertEdgeName(edge), + targetId ); computerEdge.label(edge.label()); computerEdge.properties(properties); diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java index cc58f2a3d..832c0fe5c 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java @@ -35,6 +35,7 @@ import org.apache.hugegraph.computer.core.graph.value.StringValue; import org.apache.hugegraph.computer.core.graph.value.ValueType; import org.apache.hugegraph.computer.suite.unit.UnitTestBase; +import org.apache.hugegraph.structure.graph.Edge; import org.apache.hugegraph.testutil.Assert; import org.junit.Test; @@ -126,4 +127,22 @@ public void testConvertProperties() { Assert.assertEquals(properties, HugeConverter.convertProperties(rawProperties)); } + + @Test + public void testConvertEdgeNameWithFivePartEdgeId() { + Edge edge = new Edge("belong_to_el_defect"); + edge.id("S1:178201>5>5>参数标准!3BA0>S4:239464"); + + Assert.assertEquals("参数标准!3BA0", + HugeConverter.convertEdgeName(edge)); + } + + @Test + public void testConvertEdgeNameWithSixPartEdgeId() { + Edge edge = new Edge("belong_to_el_defect"); + edge.id("S1:178201>EDGE_OUT>5>5>参数标准!3BA0>S4:239464"); + + Assert.assertEquals("参数标准!3BA0", + HugeConverter.convertEdgeName(edge)); + } } From 91a04d9478378b799256f2083af52ae3d48d416b Mon Sep 17 00:00:00 2001 From: hutiefang Date: Sun, 21 Jun 2026 21:01:39 +0800 Subject: [PATCH 2/7] fix: align edge id coverage with current HugeGraph --- .github/workflows/computer-ci.yml | 4 +--- .../computer/core/input/HugeConverter.java | 23 ++++++++++++++----- .../core/input/HugeConverterTest.java | 18 +++++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/.github/workflows/computer-ci.yml b/.github/workflows/computer-ci.yml index 266524706..336d2e471 100644 --- a/.github/workflows/computer-ci.yml +++ b/.github/workflows/computer-ci.yml @@ -22,9 +22,7 @@ jobs: TRAVIS_DIR: computer-dist/src/assembly/travis BSP_ETCD_URL: http://localhost:2579 KUBERNETES_VERSION: 1.20.1 - # TODO: adapt the HugeGraph Server/Loader version to 1.5.0 (EdgeID has 5 parts now) - # NOTE: Remember to adaptor/update the version before new release - GRAPH_ENV_VERSION: 1.3.0 + GRAPH_ENV_VERSION: 1.7.0 steps: - name: Checkout diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java index c8153e88c..094d869b9 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java @@ -42,6 +42,12 @@ public final class HugeConverter { + private static final int LEGACY_EDGE_ID_PARTS = 4; + private static final int PARENT_EDGE_ID_PARTS = 5; + private static final int DIRECTIONAL_EDGE_ID_PARTS = 6; + private static final int PARENT_EDGE_NAME_INDEX = 3; + private static final int DIRECTIONAL_EDGE_NAME_INDEX = 4; + private static final GraphFactory GRAPH_FACTORY = ComputerContext.instance().graphFactory(); @@ -107,13 +113,18 @@ public static String convertEdgeName(Edge edge) { } String[] parts = SplicingIdGenerator.split(edgeId); - if (parts.length == 4) { - return parts[2]; - } else if (parts.length == 5) { - return parts[3]; - } else if (parts.length == 6) { - return parts[4]; + if (parts.length == LEGACY_EDGE_ID_PARTS) { + return edge.name(); + } else if (parts.length == PARENT_EDGE_ID_PARTS) { + return parts[PARENT_EDGE_NAME_INDEX]; + } else if (parts.length == DIRECTIONAL_EDGE_ID_PARTS && + isEdgeDirection(parts[1])) { + return parts[DIRECTIONAL_EDGE_NAME_INDEX]; } return edge.name(); } + + private static boolean isEdgeDirection(String part) { + return "EDGE_OUT".equals(part) || "EDGE_IN".equals(part); + } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java index 832c0fe5c..160c3011c 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java @@ -128,6 +128,15 @@ public void testConvertProperties() { HugeConverter.convertProperties(rawProperties)); } + @Test + public void testConvertEdgeNameWithLegacyFourPartEdgeId() { + Edge edge = new Edge("belong_to_el_defect"); + edge.id("S1:178201>5>参数标准!3BA0>S4:239464"); + + Assert.assertEquals("参数标准!3BA0", + HugeConverter.convertEdgeName(edge)); + } + @Test public void testConvertEdgeNameWithFivePartEdgeId() { Edge edge = new Edge("belong_to_el_defect"); @@ -145,4 +154,13 @@ public void testConvertEdgeNameWithSixPartEdgeId() { Assert.assertEquals("参数标准!3BA0", HugeConverter.convertEdgeName(edge)); } + + @Test + public void testConvertEdgeNameWithSixPartInEdgeId() { + Edge edge = new Edge("belong_to_el_defect"); + edge.id("S4:239464>EDGE_IN>5>5>参数标准!3BA0>S1:178201"); + + Assert.assertEquals("参数标准!3BA0", + HugeConverter.convertEdgeName(edge)); + } } From 252ea404528e2f33df82be524cd0a1592e0cce94 Mon Sep 17 00:00:00 2001 From: hutiefang Date: Mon, 22 Jun 2026 19:33:13 +0800 Subject: [PATCH 3/7] fix: parse legacy edge names from edge ids --- .../hugegraph/computer/core/input/HugeConverter.java | 3 ++- .../hugegraph/computer/core/input/HugeConverterTest.java | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java index 094d869b9..b393d3703 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java @@ -45,6 +45,7 @@ public final class HugeConverter { private static final int LEGACY_EDGE_ID_PARTS = 4; private static final int PARENT_EDGE_ID_PARTS = 5; private static final int DIRECTIONAL_EDGE_ID_PARTS = 6; + private static final int LEGACY_EDGE_NAME_INDEX = 2; private static final int PARENT_EDGE_NAME_INDEX = 3; private static final int DIRECTIONAL_EDGE_NAME_INDEX = 4; @@ -114,7 +115,7 @@ public static String convertEdgeName(Edge edge) { String[] parts = SplicingIdGenerator.split(edgeId); if (parts.length == LEGACY_EDGE_ID_PARTS) { - return edge.name(); + return parts[LEGACY_EDGE_NAME_INDEX]; } else if (parts.length == PARENT_EDGE_ID_PARTS) { return parts[PARENT_EDGE_NAME_INDEX]; } else if (parts.length == DIRECTIONAL_EDGE_ID_PARTS && diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java index 160c3011c..a7d29dd39 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java @@ -38,6 +38,7 @@ import org.apache.hugegraph.structure.graph.Edge; import org.apache.hugegraph.testutil.Assert; import org.junit.Test; +import org.mockito.Mockito; import com.google.common.collect.ImmutableList; @@ -130,8 +131,10 @@ public void testConvertProperties() { @Test public void testConvertEdgeNameWithLegacyFourPartEdgeId() { - Edge edge = new Edge("belong_to_el_defect"); - edge.id("S1:178201>5>参数标准!3BA0>S4:239464"); + Edge edge = Mockito.mock(Edge.class); + Mockito.when(edge.id()).thenReturn( + "S1:178201>5>参数标准!3BA0>S4:239464"); + Mockito.when(edge.name()).thenReturn("stale_client_name"); Assert.assertEquals("参数标准!3BA0", HugeConverter.convertEdgeName(edge)); From b84879d8875fef36125732ef916b53cb8be03104 Mon Sep 17 00:00:00 2001 From: hutiefang Date: Tue, 23 Jun 2026 01:42:07 +0800 Subject: [PATCH 4/7] fix: tolerate current edge label schema fields --- .../core/output/hg/task/TaskManager.java | 5 +- .../computer/core/util/HugeClientUtil.java | 85 +++++++++++++++++++ .../core/input/hg/HugeGraphFetcher.java | 5 +- .../core/input/hg/HugeInputSplitFetcher.java | 7 +- .../input/hg/HugeClientCompatibilityTest.java | 57 +++++++++++++ .../computer/suite/unit/UnitTestBase.java | 4 +- 6 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java create mode 100644 computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java diff --git a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/output/hg/task/TaskManager.java b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/output/hg/task/TaskManager.java index cdeb95ed8..d71911bc2 100644 --- a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/output/hg/task/TaskManager.java +++ b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/output/hg/task/TaskManager.java @@ -28,8 +28,8 @@ import org.apache.hugegraph.computer.core.output.hg.exceptions.WriteBackException; import org.apache.hugegraph.computer.core.output.hg.metrics.LoadSummary; import org.apache.hugegraph.computer.core.output.hg.metrics.Printer; +import org.apache.hugegraph.computer.core.util.HugeClientUtil; import org.apache.hugegraph.driver.HugeClient; -import org.apache.hugegraph.driver.HugeClientBuilder; import org.apache.hugegraph.structure.graph.Vertex; import org.apache.hugegraph.util.ExecutorUtil; import org.apache.hugegraph.util.Log; @@ -58,7 +58,8 @@ public TaskManager(Config config) { String graph = config.get(ComputerOptions.HUGEGRAPH_GRAPH_NAME); String username = config.get(ComputerOptions.HUGEGRAPH_USERNAME); String password = config.get(ComputerOptions.HUGEGRAPH_PASSWORD); - this.client = new HugeClientBuilder(url, graph).configUser(username, password).build(); + this.client = HugeClientUtil.newHugeClient(url, graph, username, + password); // Try to make all batch threads running and don't wait for producer this.batchSemaphore = new Semaphore(this.batchSemaphoreNum()); /* diff --git a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java new file mode 100644 index 000000000..126c01151 --- /dev/null +++ b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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 org.apache.hugegraph.computer.core.util; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.hugegraph.driver.HugeClient; +import org.apache.hugegraph.driver.HugeClientBuilder; +import org.apache.hugegraph.rest.RestResult; +import org.apache.hugegraph.structure.schema.EdgeLabel; +import org.apache.hugegraph.util.JsonUtil; + +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder; +import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; +import com.fasterxml.jackson.databind.module.SimpleModule; + +public final class HugeClientUtil { + + private static final AtomicBoolean COMPATIBILITY_REGISTERED = + new AtomicBoolean(false); + + public static HugeClient newHugeClient(String url, String graph, + String username, String password) { + registerCompatibilityModule(); + return new HugeClientBuilder(url, graph).configUser(username, password) + .build(); + } + + public static HugeClient newHugeClient(String url, String graph, + String username, String password, + int timeout) { + registerCompatibilityModule(); + return new HugeClientBuilder(url, graph).configUser(username, password) + .configTimeout(timeout) + .build(); + } + + public static void registerCompatibilityModule() { + if (!COMPATIBILITY_REGISTERED.compareAndSet(false, true)) { + return; + } + RestResult.registerModule(newCompatibilityModule()); + JsonUtil.registerModule(newCompatibilityModule()); + } + + private static SimpleModule newCompatibilityModule() { + SimpleModule module = new SimpleModule( + "hugegraph-computer-client-compatibility"); + module.setDeserializerModifier(new BeanDeserializerModifier() { + + @Override + public BeanDeserializerBuilder updateBuilder( + DeserializationConfig config, BeanDescription beanDesc, + BeanDeserializerBuilder builder) { + if (EdgeLabel.class.equals(beanDesc.getBeanClass())) { + builder.addIgnorable("edgelabel_type"); + builder.addIgnorable("parent_label"); + builder.addIgnorable("links"); + } + return builder; + } + }); + return module; + } + + private HugeClientUtil() { + } +} diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeGraphFetcher.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeGraphFetcher.java index 813fd007c..bc546d6ea 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeGraphFetcher.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeGraphFetcher.java @@ -24,8 +24,8 @@ import org.apache.hugegraph.computer.core.input.InputSplit; import org.apache.hugegraph.computer.core.input.VertexFetcher; import org.apache.hugegraph.computer.core.rpc.InputSplitRpcService; +import org.apache.hugegraph.computer.core.util.HugeClientUtil; import org.apache.hugegraph.driver.HugeClient; -import org.apache.hugegraph.driver.HugeClientBuilder; public class HugeGraphFetcher implements GraphFetcher { @@ -39,7 +39,8 @@ public HugeGraphFetcher(Config config, InputSplitRpcService rpcService) { String graph = config.get(ComputerOptions.HUGEGRAPH_GRAPH_NAME); String username = config.get(ComputerOptions.HUGEGRAPH_USERNAME); String password = config.get(ComputerOptions.HUGEGRAPH_PASSWORD); - this.client = new HugeClientBuilder(url, graph).configUser(username, password).build(); + this.client = HugeClientUtil.newHugeClient(url, graph, username, + password); this.vertexFetcher = new HugeVertexFetcher(config, this.client); this.edgeFetcher = new HugeEdgeFetcher(config, this.client); this.rpcService = rpcService; diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeInputSplitFetcher.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeInputSplitFetcher.java index cd1654c93..0f8777549 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeInputSplitFetcher.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeInputSplitFetcher.java @@ -24,8 +24,8 @@ import org.apache.hugegraph.computer.core.config.Config; import org.apache.hugegraph.computer.core.input.InputSplit; import org.apache.hugegraph.computer.core.input.InputSplitFetcher; +import org.apache.hugegraph.computer.core.util.HugeClientUtil; import org.apache.hugegraph.driver.HugeClient; -import org.apache.hugegraph.driver.HugeClientBuilder; import org.apache.hugegraph.structure.graph.Shard; import org.apache.hugegraph.util.E; @@ -41,9 +41,8 @@ public HugeInputSplitFetcher(Config config) { String username = config.get(ComputerOptions.HUGEGRAPH_USERNAME); String password = config.get(ComputerOptions.HUGEGRAPH_PASSWORD); int timeout = config.get(ComputerOptions.INPUT_SPLIT_FETCH_TIMEOUT); - this.client = new HugeClientBuilder(url, graph).configUser(username, password) - .configTimeout(timeout) - .build(); + this.client = HugeClientUtil.newHugeClient(url, graph, username, + password, timeout); } @Override diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java new file mode 100644 index 000000000..b68ee0741 --- /dev/null +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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 org.apache.hugegraph.computer.core.input.hg; + +import org.apache.hugegraph.computer.core.util.HugeClientUtil; +import org.apache.hugegraph.rest.RestResult; +import org.apache.hugegraph.structure.schema.EdgeLabel; +import org.apache.hugegraph.testutil.Assert; +import org.junit.Test; + +public class HugeClientCompatibilityTest { + + @Test + public void testReadEdgeLabelWithCurrentServerFields() { + HugeClientUtil.registerCompatibilityModule(); + + String content = "{" + + "\"id\":1," + + "\"name\":\"link\"," + + "\"edgelabel_type\":\"NORMAL\"," + + "\"source_label\":\"user\"," + + "\"target_label\":\"user\"," + + "\"links\":[{\"user\":\"user\"}]," + + "\"frequency\":\"SINGLE\"," + + "\"sort_keys\":[]," + + "\"nullable_keys\":[]," + + "\"index_labels\":[]," + + "\"properties\":[]," + + "\"status\":\"CREATED\"," + + "\"ttl\":0," + + "\"enable_label_index\":true," + + "\"user_data\":{\"~create_time\":\"2026-06-22 15:26:42.781\"}" + + "}"; + + EdgeLabel edgeLabel = new RestResult(200, content, null).readObject( + EdgeLabel.class); + + Assert.assertEquals("link", edgeLabel.name()); + Assert.assertEquals("user", edgeLabel.sourceLabel()); + Assert.assertEquals("user", edgeLabel.targetLabel()); + } +} diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/unit/UnitTestBase.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/unit/UnitTestBase.java index 1ce8e31ab..ee9545aac 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/unit/UnitTestBase.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/unit/UnitTestBase.java @@ -46,6 +46,7 @@ import org.apache.hugegraph.computer.core.io.Writable; import org.apache.hugegraph.computer.core.store.entry.EntryInput; import org.apache.hugegraph.computer.core.store.entry.EntryInputImpl; +import org.apache.hugegraph.computer.core.util.HugeClientUtil; import org.apache.hugegraph.computer.core.util.ComputerContextUtil; import org.apache.hugegraph.computer.core.worker.MockComputationParams; import org.apache.hugegraph.config.OptionSpace; @@ -287,7 +288,8 @@ protected static StreamGraphOutput newStreamGraphOutput( protected static synchronized HugeClient client() { if (CLIENT == null) { - CLIENT = HugeClient.builder(URL, GRAPH).configUser(USERNAME, PASSWORD).build(); + CLIENT = HugeClientUtil.newHugeClient(URL, GRAPH, USERNAME, + PASSWORD); } return CLIENT; } From bc84f0a42efc738423f66b4f5021f6723d8371d4 Mon Sep 17 00:00:00 2001 From: hutiefang Date: Tue, 23 Jun 2026 20:28:05 +0800 Subject: [PATCH 5/7] test: cover edge name fallback paths --- .../core/input/HugeConverterTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java index a7d29dd39..8011db9d6 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java @@ -166,4 +166,35 @@ public void testConvertEdgeNameWithSixPartInEdgeId() { Assert.assertEquals("参数标准!3BA0", HugeConverter.convertEdgeName(edge)); } + + @Test + public void testConvertEdgeNameWithNullEdgeId() { + Edge edge = Mockito.mock(Edge.class); + Mockito.when(edge.id()).thenReturn(null); + Mockito.when(edge.name()).thenReturn("fallback_name"); + + Assert.assertEquals("fallback_name", + HugeConverter.convertEdgeName(edge)); + } + + @Test + public void testConvertEdgeNameWithUnknownEdgeIdFormat() { + Edge edge = Mockito.mock(Edge.class); + Mockito.when(edge.id()).thenReturn( + "S1:178201>VERTEX>5>5>参数标准!3BA0>S4:239464"); + Mockito.when(edge.name()).thenReturn("fallback_name"); + + Assert.assertEquals("fallback_name", + HugeConverter.convertEdgeName(edge)); + + Mockito.when(edge.id()).thenReturn("S1:178201>bad>edge"); + Assert.assertEquals("fallback_name", + HugeConverter.convertEdgeName(edge)); + } + + @Test + public void testConvertEdgeNameWithNullEdge() { + Assert.assertThrows(IllegalArgumentException.class, + () -> HugeConverter.convertEdgeName(null)); + } } From 7fa84bd022f92b8e810c294be56189016633b844 Mon Sep 17 00:00:00 2001 From: hutiefang Date: Wed, 24 Jun 2026 20:35:57 +0800 Subject: [PATCH 6/7] fix: align edge compatibility with client invariants --- .../computer/core/util/HugeClientUtil.java | 29 ++++++++++-- .../computer/core/input/HugeConverter.java | 18 ++------ .../core/input/HugeConverterTest.java | 9 ++-- .../input/hg/HugeClientCompatibilityTest.java | 45 +++++++++++++++++++ 4 files changed, 79 insertions(+), 22 deletions(-) diff --git a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java index 126c01151..12ffea5fd 100644 --- a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java +++ b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java @@ -35,6 +35,9 @@ public final class HugeClientUtil { private static final AtomicBoolean COMPATIBILITY_REGISTERED = new AtomicBoolean(false); + private static final String EDGE_LABEL_TYPE = "edgelabel_type"; + private static final String EDGE_LABEL_PARENT_LABEL = "parent_label"; + private static final String EDGE_LABEL_LINKS = "links"; public static HugeClient newHugeClient(String url, String graph, String username, String password) { @@ -70,9 +73,11 @@ public BeanDeserializerBuilder updateBuilder( DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) { if (EdgeLabel.class.equals(beanDesc.getBeanClass())) { - builder.addIgnorable("edgelabel_type"); - builder.addIgnorable("parent_label"); - builder.addIgnorable("links"); + addEdgeLabelIgnorable(builder, EDGE_LABEL_TYPE, + "edgeLabelType"); + addEdgeLabelIgnorable(builder, EDGE_LABEL_PARENT_LABEL, + "parentLabel"); + addEdgeLabelIgnorable(builder, EDGE_LABEL_LINKS, "links"); } return builder; } @@ -80,6 +85,24 @@ public BeanDeserializerBuilder updateBuilder( return module; } + private static void addEdgeLabelIgnorable(BeanDeserializerBuilder builder, + String jsonProperty, + String methodName) { + if (shouldIgnoreEdgeLabelProperty(EdgeLabel.class, methodName)) { + builder.addIgnorable(jsonProperty); + } + } + + static boolean shouldIgnoreEdgeLabelProperty(Class edgeLabelClass, + String methodName) { + try { + edgeLabelClass.getMethod(methodName); + return false; + } catch (NoSuchMethodException ignored) { + return true; + } + } + private HugeClientUtil() { } } diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java index b393d3703..1d17a337f 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverter.java @@ -43,11 +43,7 @@ public final class HugeConverter { private static final int LEGACY_EDGE_ID_PARTS = 4; - private static final int PARENT_EDGE_ID_PARTS = 5; private static final int DIRECTIONAL_EDGE_ID_PARTS = 6; - private static final int LEGACY_EDGE_NAME_INDEX = 2; - private static final int PARENT_EDGE_NAME_INDEX = 3; - private static final int DIRECTIONAL_EDGE_NAME_INDEX = 4; private static final GraphFactory GRAPH_FACTORY = ComputerContext.instance().graphFactory(); @@ -114,18 +110,10 @@ public static String convertEdgeName(Edge edge) { } String[] parts = SplicingIdGenerator.split(edgeId); - if (parts.length == LEGACY_EDGE_ID_PARTS) { - return parts[LEGACY_EDGE_NAME_INDEX]; - } else if (parts.length == PARENT_EDGE_ID_PARTS) { - return parts[PARENT_EDGE_NAME_INDEX]; - } else if (parts.length == DIRECTIONAL_EDGE_ID_PARTS && - isEdgeDirection(parts[1])) { - return parts[DIRECTIONAL_EDGE_NAME_INDEX]; + if (parts.length >= LEGACY_EDGE_ID_PARTS && + parts.length <= DIRECTIONAL_EDGE_ID_PARTS) { + return parts[parts.length - 2]; } return edge.name(); } - - private static boolean isEdgeDirection(String part) { - return "EDGE_OUT".equals(part) || "EDGE_IN".equals(part); - } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java index 8011db9d6..0049ec597 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/HugeConverterTest.java @@ -152,7 +152,7 @@ public void testConvertEdgeNameWithFivePartEdgeId() { @Test public void testConvertEdgeNameWithSixPartEdgeId() { Edge edge = new Edge("belong_to_el_defect"); - edge.id("S1:178201>EDGE_OUT>5>5>参数标准!3BA0>S4:239464"); + edge.id("S1:178201>O>5>5>参数标准!3BA0>S4:239464"); Assert.assertEquals("参数标准!3BA0", HugeConverter.convertEdgeName(edge)); @@ -161,7 +161,7 @@ public void testConvertEdgeNameWithSixPartEdgeId() { @Test public void testConvertEdgeNameWithSixPartInEdgeId() { Edge edge = new Edge("belong_to_el_defect"); - edge.id("S4:239464>EDGE_IN>5>5>参数标准!3BA0>S1:178201"); + edge.id("S4:239464>I>5>5>参数标准!3BA0>S1:178201"); Assert.assertEquals("参数标准!3BA0", HugeConverter.convertEdgeName(edge)); @@ -181,13 +181,14 @@ public void testConvertEdgeNameWithNullEdgeId() { public void testConvertEdgeNameWithUnknownEdgeIdFormat() { Edge edge = Mockito.mock(Edge.class); Mockito.when(edge.id()).thenReturn( - "S1:178201>VERTEX>5>5>参数标准!3BA0>S4:239464"); + "S1:178201>bad>edge"); Mockito.when(edge.name()).thenReturn("fallback_name"); Assert.assertEquals("fallback_name", HugeConverter.convertEdgeName(edge)); - Mockito.when(edge.id()).thenReturn("S1:178201>bad>edge"); + Mockito.when(edge.id()).thenReturn( + "S1:178201>O>5>5>参数标准!3BA0>S4:239464>extra"); Assert.assertEquals("fallback_name", HugeConverter.convertEdgeName(edge)); } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java index b68ee0741..aab81b443 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java @@ -17,6 +17,8 @@ package org.apache.hugegraph.computer.core.input.hg; +import java.lang.reflect.Method; + import org.apache.hugegraph.computer.core.util.HugeClientUtil; import org.apache.hugegraph.rest.RestResult; import org.apache.hugegraph.structure.schema.EdgeLabel; @@ -54,4 +56,47 @@ public void testReadEdgeLabelWithCurrentServerFields() { Assert.assertEquals("user", edgeLabel.sourceLabel()); Assert.assertEquals("user", edgeLabel.targetLabel()); } + + @Test + public void testIgnoreOnlyUnknownCurrentEdgeLabelFields() + throws Exception { + Assert.assertTrue(shouldIgnoreEdgeLabelProperty(EdgeLabel.class, + "edgeLabelType")); + Assert.assertTrue(shouldIgnoreEdgeLabelProperty(EdgeLabel.class, + "parentLabel")); + Assert.assertTrue(shouldIgnoreEdgeLabelProperty(EdgeLabel.class, + "links")); + + Assert.assertFalse(shouldIgnoreEdgeLabelProperty(CurrentEdgeLabel.class, + "edgeLabelType")); + Assert.assertFalse(shouldIgnoreEdgeLabelProperty(CurrentEdgeLabel.class, + "parentLabel")); + Assert.assertFalse(shouldIgnoreEdgeLabelProperty(CurrentEdgeLabel.class, + "links")); + } + + private static boolean shouldIgnoreEdgeLabelProperty(Class edgeLabelClass, + String methodName) + throws Exception { + Method method = HugeClientUtil.class.getDeclaredMethod( + "shouldIgnoreEdgeLabelProperty", Class.class, + String.class); + method.setAccessible(true); + return (boolean) method.invoke(null, edgeLabelClass, methodName); + } + + public static class CurrentEdgeLabel { + + public String edgeLabelType() { + return "NORMAL"; + } + + public String parentLabel() { + return null; + } + + public Object links() { + return null; + } + } } From 5c792eb88052879444000c36eb263375da03acda Mon Sep 17 00:00:00 2001 From: hutiefang Date: Thu, 25 Jun 2026 04:08:26 +0800 Subject: [PATCH 7/7] fix: avoid dropping current edge label fields --- .../computer/core/util/HugeClientUtil.java | 43 ++-------------- .../input/hg/HugeClientCompatibilityTest.java | 50 ++++++------------- 2 files changed, 20 insertions(+), 73 deletions(-) diff --git a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java index 12ffea5fd..aafe56417 100644 --- a/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java +++ b/computer/computer-api/src/main/java/org/apache/hugegraph/computer/core/util/HugeClientUtil.java @@ -25,19 +25,13 @@ import org.apache.hugegraph.structure.schema.EdgeLabel; import org.apache.hugegraph.util.JsonUtil; -import com.fasterxml.jackson.databind.BeanDescription; -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder; -import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.module.SimpleModule; public final class HugeClientUtil { private static final AtomicBoolean COMPATIBILITY_REGISTERED = new AtomicBoolean(false); - private static final String EDGE_LABEL_TYPE = "edgelabel_type"; - private static final String EDGE_LABEL_PARENT_LABEL = "parent_label"; - private static final String EDGE_LABEL_LINKS = "links"; public static HugeClient newHugeClient(String url, String graph, String username, String password) { @@ -66,41 +60,12 @@ public static void registerCompatibilityModule() { private static SimpleModule newCompatibilityModule() { SimpleModule module = new SimpleModule( "hugegraph-computer-client-compatibility"); - module.setDeserializerModifier(new BeanDeserializerModifier() { - - @Override - public BeanDeserializerBuilder updateBuilder( - DeserializationConfig config, BeanDescription beanDesc, - BeanDeserializerBuilder builder) { - if (EdgeLabel.class.equals(beanDesc.getBeanClass())) { - addEdgeLabelIgnorable(builder, EDGE_LABEL_TYPE, - "edgeLabelType"); - addEdgeLabelIgnorable(builder, EDGE_LABEL_PARENT_LABEL, - "parentLabel"); - addEdgeLabelIgnorable(builder, EDGE_LABEL_LINKS, "links"); - } - return builder; - } - }); + module.setMixInAnnotation(EdgeLabel.class, IgnoreUnknownFields.class); return module; } - private static void addEdgeLabelIgnorable(BeanDeserializerBuilder builder, - String jsonProperty, - String methodName) { - if (shouldIgnoreEdgeLabelProperty(EdgeLabel.class, methodName)) { - builder.addIgnorable(jsonProperty); - } - } - - static boolean shouldIgnoreEdgeLabelProperty(Class edgeLabelClass, - String methodName) { - try { - edgeLabelClass.getMethod(methodName); - return false; - } catch (NoSuchMethodException ignored) { - return true; - } + @JsonIgnoreProperties(ignoreUnknown = true) + private abstract static class IgnoreUnknownFields { } private HugeClientUtil() { diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java index aab81b443..773586182 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/input/hg/HugeClientCompatibilityTest.java @@ -25,6 +25,10 @@ import org.apache.hugegraph.testutil.Assert; import org.junit.Test; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; + public class HugeClientCompatibilityTest { @Test @@ -58,45 +62,23 @@ public void testReadEdgeLabelWithCurrentServerFields() { } @Test - public void testIgnoreOnlyUnknownCurrentEdgeLabelFields() + public void testEdgeLabelCompatibilityUsesIgnoreUnknownMixin() throws Exception { - Assert.assertTrue(shouldIgnoreEdgeLabelProperty(EdgeLabel.class, - "edgeLabelType")); - Assert.assertTrue(shouldIgnoreEdgeLabelProperty(EdgeLabel.class, - "parentLabel")); - Assert.assertTrue(shouldIgnoreEdgeLabelProperty(EdgeLabel.class, - "links")); + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(newCompatibilityModule()); + + Class mixIn = mapper.getDeserializationConfig() + .findMixInClassFor(EdgeLabel.class); + JsonIgnoreProperties annotation = mixIn.getAnnotation( + JsonIgnoreProperties.class); - Assert.assertFalse(shouldIgnoreEdgeLabelProperty(CurrentEdgeLabel.class, - "edgeLabelType")); - Assert.assertFalse(shouldIgnoreEdgeLabelProperty(CurrentEdgeLabel.class, - "parentLabel")); - Assert.assertFalse(shouldIgnoreEdgeLabelProperty(CurrentEdgeLabel.class, - "links")); + Assert.assertTrue(annotation.ignoreUnknown()); } - private static boolean shouldIgnoreEdgeLabelProperty(Class edgeLabelClass, - String methodName) - throws Exception { + private static SimpleModule newCompatibilityModule() throws Exception { Method method = HugeClientUtil.class.getDeclaredMethod( - "shouldIgnoreEdgeLabelProperty", Class.class, - String.class); + "newCompatibilityModule"); method.setAccessible(true); - return (boolean) method.invoke(null, edgeLabelClass, methodName); - } - - public static class CurrentEdgeLabel { - - public String edgeLabelType() { - return "NORMAL"; - } - - public String parentLabel() { - return null; - } - - public Object links() { - return null; - } + return (SimpleModule) method.invoke(null); } }