diff --git a/.asf.yaml b/.asf.yaml index 3f53bf5883..2cc4b1d1b4 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -18,9 +18,8 @@ github: features: issues: true - # Enable wiki for documentation wiki: true - # Enable projects for project management boards + # Enable projects for project (task)management boards projects: true discussions: true description: A graph database that supports more than 100+ billion data, high performance and scalability (Include OLTP Engine & REST-API & Backends) @@ -46,11 +45,12 @@ github: required_pull_request_reviews: dismiss_stale_reviews: true require_code_owner_reviews: false - required_approving_review_count: 2 + required_approving_review_count: 1 # (for non-committer): assign/edit/close issues & PR, without write access to the code collaborators: - - Pengzna - haohao0103 + - kenssa4eedfd + - Tsukilc # refer https://cwiki.apache.org/confluence/display/INFRA/Git+-+.asf.yaml+features#Git.asf.yamlfeatures-Notificationsettingsforrepositories notifications: diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java index c94725737f..920d119d45 100644 --- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java +++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java @@ -389,7 +389,7 @@ public class ServerOptions extends OptionHolder { "batch.max_vertices_per_batch", "The maximum number of vertices submitted per batch.", positiveInt(), - 500 + 2500 ); public static final ConfigOption MAX_EDGES_PER_BATCH = @@ -397,7 +397,7 @@ public class ServerOptions extends OptionHolder { "batch.max_edges_per_batch", "The maximum number of edges submitted per batch.", positiveInt(), - 500 + 2500 ); public static final ConfigOption MAX_WRITE_RATIO = @@ -406,7 +406,7 @@ public class ServerOptions extends OptionHolder { "The maximum thread ratio for batch writing, " + "only take effect if the batch.max_write_threads is 0.", rangeInt(0, 100), - 50 + 70 ); public static final ConfigOption MAX_WRITE_THREADS = diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java index 410b094fb9..32937a2cf0 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java @@ -61,7 +61,7 @@ public class EdgeLabelBuilder extends AbstractBuilder private Set properties; private List sortKeys; private Set nullableKeys; - private long ttl; + private Long ttl; private String ttlStartTime; private Boolean enableLabelIndex; private Userdata userdata; @@ -80,7 +80,7 @@ public EdgeLabelBuilder(ISchemaTransaction transaction, this.properties = new HashSet<>(); this.sortKeys = new ArrayList<>(); this.nullableKeys = new HashSet<>(); - this.ttl = 0L; + this.ttl = null; this.ttlStartTime = null; this.enableLabelIndex = null; this.userdata = new Userdata(); @@ -122,11 +122,7 @@ public EdgeLabel build() { } edgeLabel.frequency(this.frequency == Frequency.DEFAULT ? Frequency.SINGLE : this.frequency); - edgeLabel.ttl(this.ttl); - if (this.ttlStartTime != null) { - edgeLabel.ttlStartTime(this.graph().propertyKey( - this.ttlStartTime).id()); - } + this.updateTTL(edgeLabel); edgeLabel.enableLabelIndex(this.enableLabelIndex == null || this.enableLabelIndex); for (String key : this.properties) { @@ -209,7 +205,7 @@ public EdgeLabel create() { this.checkSortKeys(); this.checkNullableKeys(Action.INSERT); Userdata.check(this.userdata, Action.INSERT); - this.checkTtl(); + this.checkTTL(); this.checkUserdata(Action.INSERT); edgeLabel = this.build(); @@ -312,6 +308,7 @@ public EdgeLabel append() { PropertyKey propertyKey = this.graph().propertyKey(key); edgeLabel.nullableKey(propertyKey.id()); } + this.updateTTL(edgeLabel); edgeLabel.userdata(this.userdata); this.graph().updateEdgeLabel(edgeLabel); return edgeLabel; @@ -670,7 +667,35 @@ private void checkStableVars() { } } - private void checkTtl() { + /** + * Update TTL in two cases: + * 1) ttl > 0L: set or change a positive TTL + * 2) ttl == 0L and existing ttl > 0L: explicitly clear an existing TTL + * This allows removing TTL from a label that previously had TTL configured. + * Note: ttl == null means not set, so we skip the update. + */ + private void updateTTL(EdgeLabel edgeLabel) { + if (this.ttl == null) { + return; + } + if (this.ttl > 0L) { + edgeLabel.ttl(this.ttl); + if (this.ttlStartTime != null) { + edgeLabel.ttlStartTime(this.graph().propertyKey(this.ttlStartTime).id()); + } + } else if (this.ttl == 0L && edgeLabel.ttl() > 0L) { + // Clear TTL and ttlStartTime + edgeLabel.ttl(0L); + edgeLabel.ttlStartTime(IdGenerator.ZERO); + } + } + + private void checkTTL() { + if (this.ttl == null) { + E.checkArgument(this.ttlStartTime == null, + "Can't set ttl start time if ttl is not set"); + return; + } E.checkArgument(this.ttl >= 0, "The ttl must be >= 0, but got: %s", this.ttl); if (this.ttl == 0L) { diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java index 53b6cabddb..4962646209 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/VertexLabelBuilder.java @@ -52,7 +52,7 @@ public class VertexLabelBuilder extends AbstractBuilder implements VertexLabel.B private final Set properties; private final List primaryKeys; private final Set nullableKeys; - private long ttl; + private Long ttl; private String ttlStartTime; private Boolean enableLabelIndex; private final Userdata userdata; @@ -68,7 +68,7 @@ public VertexLabelBuilder(ISchemaTransaction transaction, this.properties = new HashSet<>(); this.primaryKeys = new ArrayList<>(); this.nullableKeys = new HashSet<>(); - this.ttl = 0L; + this.ttl = null; this.ttlStartTime = null; this.enableLabelIndex = null; this.userdata = new Userdata(); @@ -99,13 +99,8 @@ public VertexLabel build() { this.id, this.name); VertexLabel vertexLabel = new VertexLabel(this.graph(), id, this.name); vertexLabel.idStrategy(this.idStrategy); - vertexLabel.enableLabelIndex(this.enableLabelIndex == null || - this.enableLabelIndex); - vertexLabel.ttl(this.ttl); - if (this.ttlStartTime != null) { - vertexLabel.ttlStartTime(this.graph().propertyKey( - this.ttlStartTime).id()); - } + vertexLabel.enableLabelIndex(this.enableLabelIndex == null || this.enableLabelIndex); + this.updateTTL(vertexLabel); // Assign properties for (String key : this.properties) { PropertyKey propertyKey = this.graph().propertyKey(key); @@ -142,7 +137,7 @@ public VertexLabel create() { this.checkIdStrategy(); this.checkNullableKeys(Action.INSERT); Userdata.check(this.userdata, Action.INSERT); - this.checkTtl(); + this.checkTTL(); this.checkUserdata(Action.INSERT); vertexLabel = this.build(); @@ -225,6 +220,7 @@ public VertexLabel append() { PropertyKey propertyKey = this.graph().propertyKey(key); vertexLabel.nullableKey(propertyKey.id()); } + this.updateTTL(vertexLabel); vertexLabel.userdata(this.userdata); this.graph().updateVertexLabel(vertexLabel); return vertexLabel; @@ -276,8 +272,7 @@ public VertexLabelBuilder id(long id) { @Override public VertexLabelBuilder idStrategy(IdStrategy idStrategy) { - E.checkArgument(this.idStrategy == IdStrategy.DEFAULT || - this.idStrategy == idStrategy, + E.checkArgument(this.idStrategy == IdStrategy.DEFAULT || this.idStrategy == idStrategy, "Not allowed to change id strategy for " + "vertex label '%s'", this.name); this.idStrategy = idStrategy; @@ -434,18 +429,15 @@ private void checkNullableKeys(Action action) { if (action == Action.ELIMINATE) { if (!this.nullableKeys.isEmpty()) { throw new NotAllowException( - "Not support to eliminate nullableKeys " + - "for vertex label currently"); + "Not support to eliminate nullableKeys for vertex label currently"); } return; } VertexLabel vertexLabel = this.vertexLabelOrNull(this.name); // The originProps is empty when firstly create vertex label - List originProps = vertexLabel == null ? - ImmutableList.of() : - this.graph() - .mapPkId2Name(vertexLabel.properties()); + List originProps = vertexLabel == null ? ImmutableList.of() : + this.graph().mapPkId2Name(vertexLabel.properties()); Set appendProps = this.properties; E.checkArgument(CollectionUtil.union(originProps, appendProps) @@ -454,10 +446,8 @@ private void checkNullableKeys(Action action) { "must belong to the origin/new properties: %s/%s", this.nullableKeys, originProps, appendProps); - List primaryKeys = vertexLabel == null ? - this.primaryKeys : - this.graph() - .mapPkId2Name(vertexLabel.primaryKeys()); + List primaryKeys = vertexLabel == null ? this.primaryKeys : + this.graph().mapPkId2Name(vertexLabel.primaryKeys()); E.checkArgument(!CollectionUtil.hasIntersection(primaryKeys, this.nullableKeys), "The nullableKeys: %s are not allowed to " + @@ -465,11 +455,9 @@ private void checkNullableKeys(Action action) { this.nullableKeys, primaryKeys, this.name); if (action == Action.APPEND) { - Collection newAddedProps = CollectionUtils.subtract( - appendProps, originProps); + Collection newAddedProps = CollectionUtils.subtract(appendProps, originProps); E.checkArgument(this.nullableKeys.containsAll(newAddedProps), - "The new added properties: %s must be nullable", - newAddedProps); + "The new added properties: %s must be nullable", newAddedProps); } } @@ -498,8 +486,7 @@ private void checkIdStrategy() { "when using '%s' id strategy", strategy); break; default: - throw new AssertionError(String.format( - "Unknown id strategy '%s'", strategy)); + throw new AssertionError(String.format("Unknown id strategy '%s'", strategy)); } if (this.idStrategy == IdStrategy.PRIMARY_KEY) { this.checkPrimaryKeys(); @@ -546,7 +533,35 @@ private void checkStableVars() { } } - private void checkTtl() { + /** + * Update TTL in two cases: + * 1) ttl > 0L: set or change a positive TTL + * 2) ttl == 0L and existing ttl > 0L: explicitly clear an existing TTL + * This allows removing TTL from a label that previously had TTL configured. + * Note: ttl == null means not set, so we skip the update. + */ + private void updateTTL(VertexLabel vertexLabel) { + if (this.ttl == null) { + return; + } + if (this.ttl > 0L) { + vertexLabel.ttl(this.ttl); + if (this.ttlStartTime != null) { + vertexLabel.ttlStartTime(this.graph().propertyKey(this.ttlStartTime).id()); + } + } else if (this.ttl == 0L && vertexLabel.ttl() > 0L) { + // Clear TTL and ttlStartTime + vertexLabel.ttl(0L); + vertexLabel.ttlStartTime(IdGenerator.ZERO); + } + } + + private void checkTTL() { + if (this.ttl == null) { + E.checkArgument(this.ttlStartTime == null, + "Can't set ttl start time if ttl is not set"); + return; + } E.checkArgument(this.ttl >= 0, "The ttl must be >= 0, but got: %s", this.ttl); if (this.ttl == 0L) { @@ -588,8 +603,7 @@ private void checkUserdata(Action action) { // pass break; default: - throw new AssertionError(String.format( - "Unknown schema action '%s'", action)); + throw new AssertionError(String.format("Unknown schema action '%s'", action)); } } diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java index 3b81c2f16e..8629f78b3e 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/EdgeLabelCoreTest.java @@ -480,7 +480,7 @@ public void testAddEdgeLabelWithDisableLabelIndex() { } @Test - public void testAddEdgeLabelWithTtl() { + public void testAddEdgeLabelWithTTL() { super.initPropertyKeys(); SchemaManager schema = graph().schema(); @@ -561,6 +561,124 @@ public void testAddEdgeLabelWithTtl() { assertContainsPk(ImmutableSet.of(write.ttlStartTime()), "date"); } + @Test + public void testAppendEdgeLabelWithTTL() { + super.initPropertyKeys(); + + SchemaManager schema = graph().schema(); + + schema.propertyKey("date").asDate().ifNotExist().create(); + + schema.vertexLabel("person") + .properties("name", "age", "city") + .primaryKeys("name") + .nullableKeys("city") + .create(); + + schema.vertexLabel("book") + .properties("name") + .primaryKeys("name") + .create(); + + // Create an edge label without TTL + EdgeLabel read = schema.edgeLabel("read").link("person", "book") + .properties("date", "weight") + .create(); + + Assert.assertNotNull(read); + Assert.assertEquals("read", read.name()); + Assert.assertEquals(0L, read.ttl()); + + // Update the edge label with TTL via append + read = schema.edgeLabel("read") + .ttl(86400L) + .append(); + + Assert.assertNotNull(read); + Assert.assertEquals("read", read.name()); + Assert.assertEquals(86400L, read.ttl()); + } + + @Test + public void testAppendEdgeLabelResetTTL() { + super.initPropertyKeys(); + + SchemaManager schema = graph().schema(); + + schema.vertexLabel("person") + .properties("name", "age", "city") + .primaryKeys("name") + .nullableKeys("city") + .create(); + + schema.vertexLabel("book") + .properties("name") + .primaryKeys("name") + .create(); + + // Create an edge label with TTL + EdgeLabel read = schema.edgeLabel("read").link("person", "book") + .properties("time", "weight") + .ttl(86400L) + .create(); + + Assert.assertNotNull(read); + Assert.assertEquals("read", read.name()); + Assert.assertEquals(86400L, read.ttl()); + + // Reset TTL to 0 via append + read = schema.edgeLabel("read") + .ttl(0L) + .append(); + + Assert.assertNotNull(read); + Assert.assertEquals("read", read.name()); + Assert.assertEquals(0L, read.ttl()); + } + + @Test + public void testAppendEdgeLabelWithoutTTLShouldNotClearExistingTTL() { + super.initPropertyKeys(); + + SchemaManager schema = graph().schema(); + + schema.propertyKey("date").asDate().ifNotExist().create(); + + schema.vertexLabel("person") + .properties("name", "age", "city") + .primaryKeys("name") + .nullableKeys("city") + .create(); + + schema.vertexLabel("book") + .properties("name") + .primaryKeys("name") + .create(); + + // Create edge label with TTL and ttlStartTime + EdgeLabel read = schema.edgeLabel("read").link("person", "book") + .properties("date", "weight") + .ttl(86400L) + .ttlStartTime("date") + .create(); + + Assert.assertNotNull(read); + Assert.assertEquals(86400L, read.ttl()); + Assert.assertNotNull(read.ttlStartTime()); + assertContainsPk(ImmutableSet.of(read.ttlStartTime()), "date"); + + // Append property WITHOUT specifying ttl + read = schema.edgeLabel("read") + .nullableKeys("weight") + .append(); + + // Both TTL and ttlStartTime should remain unchanged + Assert.assertNotNull(read); + Assert.assertEquals(86400L, read.ttl()); + Assert.assertNotNull(read.ttlStartTime()); + assertContainsPk(ImmutableSet.of(read.ttlStartTime()), "date"); + } + @Test public void testAppendEdgeLabelWithUndefinedNullableKeys() { super.initPropertyKeys(); diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java index 8dafcc5953..a43731f235 100644 --- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java +++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/VertexLabelCoreTest.java @@ -566,7 +566,7 @@ public void testAddVertexLabelWithDisableLabelIndex() { } @Test - public void testAddVertexLabelWithTtl() { + public void testAddVertexLabelWithTTL() { super.initPropertyKeys(); SchemaManager schema = graph().schema(); @@ -633,6 +633,91 @@ public void testAddVertexLabelWithTtl() { assertContainsPk(ImmutableSet.of(student.ttlStartTime()), "born"); } + @Test + public void testAppendVertexLabelWithTTL() { + super.initPropertyKeys(); + + SchemaManager schema = graph().schema(); + + schema.propertyKey("born").asDate().ifNotExist().create(); + + // Create a vertex label without TTL + VertexLabel person = schema.vertexLabel("person") + .properties("name", "age", "city", "born") + .create(); + + Assert.assertNotNull(person); + Assert.assertEquals("person", person.name()); + Assert.assertEquals(0L, person.ttl()); + + // Update the vertex label with TTL via append + person = schema.vertexLabel("person") + .ttl(86400L) + .append(); + + Assert.assertNotNull(person); + Assert.assertEquals("person", person.name()); + Assert.assertEquals(86400L, person.ttl()); + } + + @Test + public void testAppendVertexLabelResetTTL() { + super.initPropertyKeys(); + + SchemaManager schema = graph().schema(); + + // Create a vertex label with TTL + VertexLabel person = schema.vertexLabel("person") + .properties("name", "age", "city") + .ttl(86400L) + .create(); + + Assert.assertNotNull(person); + Assert.assertEquals("person", person.name()); + Assert.assertEquals(86400L, person.ttl()); + + // Reset TTL to 0 via append + person = schema.vertexLabel("person") + .ttl(0L) + .append(); + + Assert.assertNotNull(person); + Assert.assertEquals("person", person.name()); + Assert.assertEquals(0L, person.ttl()); + } + + @Test + public void testAppendVertexLabelWithoutTTLShouldNotClearExistingTTL() { + super.initPropertyKeys(); + + SchemaManager schema = graph().schema(); + + schema.propertyKey("born").asDate().ifNotExist().create(); + + // Create label with TTL and ttlStartTime + VertexLabel person = schema.vertexLabel("person") + .properties("name", "age", "city", "born") + .ttl(86400L) + .ttlStartTime("born") + .create(); + + Assert.assertNotNull(person); + Assert.assertEquals(86400L, person.ttl()); + Assert.assertNotNull(person.ttlStartTime()); + assertContainsPk(ImmutableSet.of(person.ttlStartTime()), "born"); + + // Append property WITHOUT specifying ttl + person = schema.vertexLabel("person") + .nullableKeys("city") + .append(); + + // Both TTL and ttlStartTime should remain unchanged + Assert.assertNotNull(person); + Assert.assertEquals(86400L, person.ttl()); + Assert.assertNotNull(person.ttlStartTime()); + assertContainsPk(ImmutableSet.of(person.ttlStartTime()), "born"); + } + @Test public void testAppendVertexLabelWithUndefinedNullableKeys() { super.initPropertyKeys();