diff --git a/.circleci/config.yml b/.circleci/config.yml index 33bc358ab..1d30f32b3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -124,6 +124,9 @@ executors: j21: docker: - image: 'cimg/openjdk:21.0' + j23: + docker: + - image: 'cimg/openjdk:23.0' jobs: @@ -524,18 +527,21 @@ workflows: jdk: - 'j17' - 'j21' + - 'j23' filters: tags: only: /^v.*/ branches: only: - main + - next - test: name: test-jackson-<> matrix: parameters: args: - - '-Dadb.jackson.version=2.18.2' + - '-Dadb.jackson.version=2.19.0' + - '-Dadb.jackson.version=2.18.3' - '-Dadb.jackson.version=2.17.3' - '-Dadb.jackson.version=2.16.2' - '-Dadb.jackson.version=2.15.4' @@ -550,6 +556,7 @@ workflows: branches: only: - main + - next - test: name: test-native-ssl=<>-<> matrix: @@ -562,7 +569,6 @@ workflows: - 'true' - 'false' graalvm-version: - - '22.0.1-graalce' - '21.0.2-graalce' filters: tags: @@ -570,6 +576,7 @@ workflows: branches: only: - main + - next - test-shaded: name: test-native-shaded-ssl=<>-<> matrix: @@ -582,7 +589,6 @@ workflows: - 'true' - 'false' graalvm-version: - - '22.0.1-graalce' - '21.0.2-graalce' filters: tags: @@ -590,6 +596,7 @@ workflows: branches: only: - main + - next - test: name: test-activefailover-<> matrix: @@ -605,6 +612,7 @@ workflows: branches: only: - main + - next test-non-func: when: diff --git a/ChangeLog.md b/ChangeLog.md index 7cdd37020..7137b9814 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,12 +6,38 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +## [7.20.0] - 2025-06-17 + +- added option `usePlanCache` to `AqlQueryOptions` (DE-973, #609) +- updated Jackson version to `2.19` (DE-1012, #607) + +## [7.19.0] - 2025-05-28 + +- fixed connection pool load-balancing (DE-1016, #602), now the connection pool: + - keeps track of busy connections (or busy HTTP/2 streams) + - enqueues new requests only to connections that are not busy (or that have available HTTP/2 streams) + - waits asynchronously if all the connections are busy (or all HTTP/2 streams are busy) +- added new option to configure HTTP/1.1 pipelining (`com.arangodb.ArangoDB.Builder.pipelining(Boolean)`), + `false` by default +- changed default configuration HTTP/1.1 pipelining to `false` + +## [7.18.0] - 2025-05-06 + +- updated `jackson-dataformat-velocypack` to version `4.6.0` +- exposed configuration properties keys in `ArangoConfigProperties` +- deprecated `CollectionStatus` +- fixed `equals()` and `hashCode()` in some entity classes + +## [7.17.1] - 2025-03-27 + +- implemented `equals()` and `hashCode()` for all entity classes +- fixed overlapping resources in shaded package + ## [7.17.0] - 2025-01-27 - allow construct ArangoConfigProperties from `java.util.Properties` (DE-976) - made BaseDocument and BaseEdgeDocument serializable (#596) - ## [7.16.0] - 2025-01-09 - improved deserialization of `RawBytes` and `RawJson` (#592, DE-969) diff --git a/core/pom.xml b/core/pom.xml index c5ee7e166..77c2dd875 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 core diff --git a/core/src/main/java/com/arangodb/ArangoDB.java b/core/src/main/java/com/arangodb/ArangoDB.java index ea822d89e..7ebdb2e7e 100644 --- a/core/src/main/java/com/arangodb/ArangoDB.java +++ b/core/src/main/java/com/arangodb/ArangoDB.java @@ -517,6 +517,17 @@ public Builder chunkSize(final Integer chunkSize) { return this; } + /** + * Set whether to use requests pipelining in HTTP/1.1 ({@link Protocol#HTTP_JSON} or {@link Protocol#HTTP_VPACK}). + * + * @param pipelining {@code true} if enabled + * @return {@link ArangoDB.Builder} + */ + public Builder pipelining(final Boolean pipelining) { + config.setPipelining(pipelining); + return this; + } + /** * Sets the maximum number of connections the built in connection pool will open per host. * @@ -528,6 +539,8 @@ public Builder chunkSize(final Integer chunkSize) { * {@link Protocol#VST} == 1 * {@link Protocol#HTTP_JSON} == 20 * {@link Protocol#HTTP_VPACK} == 20 + * {@link Protocol#HTTP2_JSON} == 1 + * {@link Protocol#HTTP2_VPACK} == 1 * * * @param maxConnections max number of connections diff --git a/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java b/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java index 1a67eb3fb..832c8862d 100644 --- a/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java +++ b/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java @@ -11,6 +11,30 @@ public interface ArangoConfigProperties { + //region configuration properties keys + String KEY_HOSTS = "hosts"; + String KEY_PROTOCOL = "protocol"; + String KEY_USER = "user"; + String KEY_PASSWORD = "password"; + String KEY_JWT = "jwt"; + String KEY_TIMEOUT = "timeout"; + String KEY_USE_SSL = "useSsl"; + String KEY_VERIFY_HOST = "verifyHost"; + String KEY_CHUNK_SIZE = "chunkSize"; + String KEY_PIPELINING = "pipelining"; + String KEY_MAX_CONNECTIONS = "maxConnections"; + String KEY_CONNECTION_TTL = "connectionTtl"; + String KEY_KEEP_ALIVE_INTERVAL = "keepAliveInterval"; + String KEY_ACQUIRE_HOST_LIST = "acquireHostList"; + String KEY_ACQUIRE_HOST_LIST_INTERVAL = "acquireHostListInterval"; + String KEY_LOAD_BALANCING_STRATEGY = "loadBalancingStrategy"; + String KEY_RESPONSE_QUEUE_TIME_SAMPLES = "responseQueueTimeSamples"; + String KEY_COMPRESSION = "compression"; + String KEY_COMPRESSION_THRESHOLD = "compressionThreshold"; + String KEY_COMPRESSION_LEVEL = "compressionLevel"; + String KEY_SERDE_PROVIDER_CLASS = "serdeProviderClass"; + //endregion + /** * Reads properties from file arangodb.properties. * Properties must be prefixed with @{code "arangodb"}, eg. @{code "arangodb.hosts=localhost:8529"}. @@ -87,6 +111,10 @@ default Optional getChunkSize() { return Optional.empty(); } + default Optional getPipelining() { + return Optional.empty(); + } + default Optional getMaxConnections() { return Optional.empty(); } diff --git a/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java b/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java index 6f6448b14..eb56fc74b 100644 --- a/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Map; +import java.util.Objects; /** * @author Mark Vollmary @@ -59,6 +60,18 @@ public Boolean getCacheable() { return cacheable; } + @Override + public boolean equals(Object o) { + if (!(o instanceof AqlExecutionExplainEntity)) return false; + AqlExecutionExplainEntity that = (AqlExecutionExplainEntity) o; + return Objects.equals(plan, that.plan) && Objects.equals(plans, that.plans) && Objects.equals(warnings, that.warnings) && Objects.equals(stats, that.stats) && Objects.equals(cacheable, that.cacheable); + } + + @Override + public int hashCode() { + return Objects.hash(plan, plans, warnings, stats, cacheable); + } + public static final class ExecutionPlan { private Collection nodes; private Collection rules; @@ -90,6 +103,18 @@ public Integer getEstimatedCost() { public Integer getEstimatedNrItems() { return estimatedNrItems; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionPlan)) return false; + ExecutionPlan that = (ExecutionPlan) o; + return Objects.equals(nodes, that.nodes) && Objects.equals(rules, that.rules) && Objects.equals(collections, that.collections) && Objects.equals(variables, that.variables) && Objects.equals(estimatedCost, that.estimatedCost) && Objects.equals(estimatedNrItems, that.estimatedNrItems); + } + + @Override + public int hashCode() { + return Objects.hash(nodes, rules, collections, variables, estimatedCost, estimatedNrItems); + } } public static final class ExecutionNode { @@ -208,6 +233,18 @@ public ExecutionCollection getCondition() { public Boolean getReverse() { return reverse; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionNode)) return false; + ExecutionNode that = (ExecutionNode) o; + return Objects.equals(type, that.type) && Objects.equals(dependencies, that.dependencies) && Objects.equals(id, that.id) && Objects.equals(estimatedCost, that.estimatedCost) && Objects.equals(estimatedNrItems, that.estimatedNrItems) && Objects.equals(depth, that.depth) && Objects.equals(database, that.database) && Objects.equals(collection, that.collection) && Objects.equals(inVariable, that.inVariable) && Objects.equals(outVariable, that.outVariable) && Objects.equals(conditionVariable, that.conditionVariable) && Objects.equals(random, that.random) && Objects.equals(offset, that.offset) && Objects.equals(limit, that.limit) && Objects.equals(fullCount, that.fullCount) && Objects.equals(subquery, that.subquery) && Objects.equals(isConst, that.isConst) && Objects.equals(canThrow, that.canThrow) && Objects.equals(expressionType, that.expressionType) && Objects.equals(indexes, that.indexes) && Objects.equals(expression, that.expression) && Objects.equals(condition, that.condition) && Objects.equals(reverse, that.reverse); + } + + @Override + public int hashCode() { + return Objects.hash(type, dependencies, id, estimatedCost, estimatedNrItems, depth, database, collection, inVariable, outVariable, conditionVariable, random, offset, limit, fullCount, subquery, isConst, canThrow, expressionType, indexes, expression, condition, reverse); + } } public static final class ExecutionVariable { @@ -221,6 +258,18 @@ public Long getId() { public String getName() { return name; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionVariable)) return false; + ExecutionVariable that = (ExecutionVariable) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } } public static final class ExecutionExpression { @@ -264,6 +313,18 @@ public Collection getLevels() { public Collection getSubNodes() { return subNodes; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionExpression)) return false; + ExecutionExpression that = (ExecutionExpression) o; + return Objects.equals(type, that.type) && Objects.equals(name, that.name) && Objects.equals(id, that.id) && Objects.equals(value, that.value) && Objects.equals(sorted, that.sorted) && Objects.equals(quantifier, that.quantifier) && Objects.equals(levels, that.levels) && Objects.equals(subNodes, that.subNodes); + } + + @Override + public int hashCode() { + return Objects.hash(type, name, id, value, sorted, quantifier, levels, subNodes); + } } public static final class ExecutionCollection { @@ -277,6 +338,18 @@ public String getName() { public String getType() { return type; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionCollection)) return false; + ExecutionCollection that = (ExecutionCollection) o; + return Objects.equals(name, that.name) && Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return Objects.hash(name, type); + } } public static final class ExecutionStats { @@ -305,6 +378,18 @@ public Long getPeakMemoryUsage() { public Double getExecutionTime() { return executionTime; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionStats)) return false; + ExecutionStats that = (ExecutionStats) o; + return Objects.equals(rulesExecuted, that.rulesExecuted) && Objects.equals(rulesSkipped, that.rulesSkipped) && Objects.equals(plansCreated, that.plansCreated) && Objects.equals(peakMemoryUsage, that.peakMemoryUsage) && Objects.equals(executionTime, that.executionTime); + } + + @Override + public int hashCode() { + return Objects.hash(rulesExecuted, rulesSkipped, plansCreated, peakMemoryUsage, executionTime); + } } } diff --git a/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java b/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java index 81026a26d..78ff58921 100644 --- a/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -56,4 +58,15 @@ public Boolean getIsDeterministic() { return isDeterministic; } + @Override + public boolean equals(Object o) { + if (!(o instanceof AqlFunctionEntity)) return false; + AqlFunctionEntity that = (AqlFunctionEntity) o; + return Objects.equals(name, that.name) && Objects.equals(code, that.code) && Objects.equals(isDeterministic, that.isDeterministic); + } + + @Override + public int hashCode() { + return Objects.hash(name, code, isDeterministic); + } } diff --git a/core/src/main/java/com/arangodb/entity/AqlParseEntity.java b/core/src/main/java/com/arangodb/entity/AqlParseEntity.java index 15bcc82e1..3dd7bf9ac 100644 --- a/core/src/main/java/com/arangodb/entity/AqlParseEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlParseEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -43,6 +44,18 @@ public Collection getAst() { return ast; } + @Override + public boolean equals(Object o) { + if (!(o instanceof AqlParseEntity)) return false; + AqlParseEntity that = (AqlParseEntity) o; + return Objects.equals(collections, that.collections) && Objects.equals(bindVars, that.bindVars) && Objects.equals(ast, that.ast); + } + + @Override + public int hashCode() { + return Objects.hash(collections, bindVars, ast); + } + public static final class AstNode { private String type; private Collection subNodes; @@ -70,6 +83,17 @@ public Object getValue() { return value; } + @Override + public boolean equals(Object o) { + if (!(o instanceof AstNode)) return false; + AstNode astNode = (AstNode) o; + return Objects.equals(type, astNode.type) && Objects.equals(subNodes, astNode.subNodes) && Objects.equals(name, astNode.name) && Objects.equals(id, astNode.id) && Objects.equals(value, astNode.value); + } + + @Override + public int hashCode() { + return Objects.hash(type, subNodes, name, id, value); + } } } diff --git a/core/src/main/java/com/arangodb/entity/AqlQueryExplainEntity.java b/core/src/main/java/com/arangodb/entity/AqlQueryExplainEntity.java index cc200bfda..c4eb9ea22 100644 --- a/core/src/main/java/com/arangodb/entity/AqlQueryExplainEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlQueryExplainEntity.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; public final class AqlQueryExplainEntity { @@ -54,6 +55,18 @@ public Boolean getCacheable() { return cacheable; } + @Override + public boolean equals(Object o) { + if (!(o instanceof AqlQueryExplainEntity)) return false; + AqlQueryExplainEntity that = (AqlQueryExplainEntity) o; + return Objects.equals(plan, that.plan) && Objects.equals(plans, that.plans) && Objects.equals(warnings, that.warnings) && Objects.equals(stats, that.stats) && Objects.equals(cacheable, that.cacheable); + } + + @Override + public int hashCode() { + return Objects.hash(plan, plans, warnings, stats, cacheable); + } + public static final class ExecutionPlan { private final Map properties = new HashMap<>(); private Collection nodes; @@ -90,6 +103,18 @@ public Collection getRules() { public Collection getVariables() { return variables; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionPlan)) return false; + ExecutionPlan that = (ExecutionPlan) o; + return Objects.equals(properties, that.properties) && Objects.equals(nodes, that.nodes) && Objects.equals(estimatedCost, that.estimatedCost) && Objects.equals(collections, that.collections) && Objects.equals(rules, that.rules) && Objects.equals(variables, that.variables); + } + + @Override + public int hashCode() { + return Objects.hash(properties, nodes, estimatedCost, collections, rules, variables); + } } public static final class ExecutionNode { @@ -103,6 +128,18 @@ public void add(String key, Object value) { public Object get(String key) { return properties.get(key); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionNode)) return false; + ExecutionNode that = (ExecutionNode) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hashCode(properties); + } } public static final class ExecutionVariable { @@ -116,6 +153,18 @@ public void add(String key, Object value) { public Object get(String key) { return properties.get(key); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionVariable)) return false; + ExecutionVariable that = (ExecutionVariable) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hashCode(properties); + } } public static final class ExecutionCollection { @@ -129,6 +178,18 @@ public void add(String key, Object value) { public Object get(String key) { return properties.get(key); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionCollection)) return false; + ExecutionCollection that = (ExecutionCollection) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hashCode(properties); + } } public static final class ExecutionStats { @@ -142,6 +203,18 @@ public void add(String key, Object value) { public Object get(String key) { return properties.get(key); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ExecutionStats)) return false; + ExecutionStats that = (ExecutionStats) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hashCode(properties); + } } } diff --git a/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java index 3318c3d7c..30f811800 100644 --- a/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java +++ b/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Michele Rastelli */ @@ -38,6 +40,18 @@ public StorageEngineName getName() { return name; } + @Override + public boolean equals(Object o) { + if (!(o instanceof ArangoDBEngine)) return false; + ArangoDBEngine that = (ArangoDBEngine) o; + return name == that.name; + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } + public enum StorageEngineName { mmfiles, rocksdb } diff --git a/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java b/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java index d67e5ab4b..6fd696166 100644 --- a/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java +++ b/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -55,4 +57,15 @@ public License getLicense() { return license; } + @Override + public boolean equals(Object o) { + if (!(o instanceof ArangoDBVersion)) return false; + ArangoDBVersion that = (ArangoDBVersion) o; + return Objects.equals(server, that.server) && Objects.equals(version, that.version) && license == that.license; + } + + @Override + public int hashCode() { + return Objects.hash(server, version, license); + } } \ No newline at end of file diff --git a/core/src/main/java/com/arangodb/entity/CollectionEntity.java b/core/src/main/java/com/arangodb/entity/CollectionEntity.java index 43eef1d17..45ddeaf12 100644 --- a/core/src/main/java/com/arangodb/entity/CollectionEntity.java +++ b/core/src/main/java/com/arangodb/entity/CollectionEntity.java @@ -24,6 +24,7 @@ import com.arangodb.model.ComputedValue; import java.util.List; +import java.util.Objects; /** * @author Mark Vollmary @@ -59,6 +60,7 @@ public Boolean getIsSystem() { return isSystem; } + @Deprecated public CollectionStatus getStatus() { return status; } @@ -83,4 +85,15 @@ public List getComputedValues() { return computedValues; } + @Override + public boolean equals(Object o) { + if (!(o instanceof CollectionEntity)) return false; + CollectionEntity that = (CollectionEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(waitForSync, that.waitForSync) && Objects.equals(isSystem, that.isSystem) && status == that.status && type == that.type && Objects.equals(schema, that.schema) && Objects.equals(computedValues, that.computedValues); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, waitForSync, isSystem, status, type, schema, computedValues); + } } diff --git a/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 0e19d658e..8f5076639 100644 --- a/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -148,4 +149,17 @@ public Long getCount() { public void setCount(Long count) { this.count = count; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof CollectionPropertiesEntity)) return false; + if (!super.equals(o)) return false; + CollectionPropertiesEntity that = (CollectionPropertiesEntity) o; + return Objects.equals(cacheEnabled, that.cacheEnabled) && Objects.equals(distributeShardsLike, that.distributeShardsLike) && Objects.equals(isDisjoint, that.isDisjoint) && Objects.equals(isSmart, that.isSmart) && Objects.equals(keyOptions, that.keyOptions) && Objects.equals(numberOfShards, that.numberOfShards) && Objects.equals(replicationFactor, that.replicationFactor) && Objects.equals(shardKeys, that.shardKeys) && Objects.equals(shardingStrategy, that.shardingStrategy) && Objects.equals(smartGraphAttribute, that.smartGraphAttribute) && Objects.equals(smartJoinAttribute, that.smartJoinAttribute) && Objects.equals(writeConcern, that.writeConcern) && Objects.equals(count, that.count); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), cacheEnabled, distributeShardsLike, isDisjoint, isSmart, keyOptions, numberOfShards, replicationFactor, shardKeys, shardingStrategy, smartGraphAttribute, smartJoinAttribute, writeConcern, count); + } } diff --git a/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java b/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java index 6e90e456a..02e8e2ae3 100644 --- a/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java +++ b/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -31,4 +33,16 @@ public String getRevision() { return revision; } + @Override + public boolean equals(Object o) { + if (!(o instanceof CollectionRevisionEntity)) return false; + if (!super.equals(o)) return false; + CollectionRevisionEntity that = (CollectionRevisionEntity) o; + return Objects.equals(revision, that.revision); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), revision); + } } diff --git a/core/src/main/java/com/arangodb/entity/CollectionStatus.java b/core/src/main/java/com/arangodb/entity/CollectionStatus.java index b3d30f5d6..39b7863b9 100644 --- a/core/src/main/java/com/arangodb/entity/CollectionStatus.java +++ b/core/src/main/java/com/arangodb/entity/CollectionStatus.java @@ -23,6 +23,7 @@ /** * @author Mark Vollmary */ +@Deprecated public enum CollectionStatus { LOADED(3), DELETED(5); diff --git a/core/src/main/java/com/arangodb/entity/CursorEntity.java b/core/src/main/java/com/arangodb/entity/CursorEntity.java index 71b34f31d..6070ddc1a 100644 --- a/core/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/core/src/main/java/com/arangodb/entity/CursorEntity.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Objects; /** * @author Mark Vollmary @@ -110,6 +111,18 @@ public String getNextBatchId() { return nextBatchId; } + @Override + public boolean equals(Object o) { + if (!(o instanceof CursorEntity)) return false; + CursorEntity that = (CursorEntity) o; + return Objects.equals(id, that.id) && Objects.equals(count, that.count) && Objects.equals(cached, that.cached) && Objects.equals(hasMore, that.hasMore) && Objects.equals(result, that.result) && Objects.equals(potentialDirtyRead, that.potentialDirtyRead) && Objects.equals(nextBatchId, that.nextBatchId) && Objects.equals(extra, that.extra); + } + + @Override + public int hashCode() { + return Objects.hash(id, count, cached, hasMore, result, potentialDirtyRead, nextBatchId, extra); + } + public static final class Extras { private final Collection warnings = Collections.emptyList(); private CursorStats stats; @@ -121,6 +134,18 @@ public CursorStats getStats() { public Collection getWarnings() { return warnings; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Extras)) return false; + Extras extras = (Extras) o; + return Objects.equals(warnings, extras.warnings) && Objects.equals(stats, extras.stats); + } + + @Override + public int hashCode() { + return Objects.hash(warnings, stats); + } } } diff --git a/core/src/main/java/com/arangodb/entity/CursorStats.java b/core/src/main/java/com/arangodb/entity/CursorStats.java index 338b93d14..2d5ce96a3 100644 --- a/core/src/main/java/com/arangodb/entity/CursorStats.java +++ b/core/src/main/java/com/arangodb/entity/CursorStats.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; public final class CursorStats { private final Map properties = new HashMap<>(); @@ -171,4 +172,16 @@ public Integer getIntermediateCommits() { public Integer getSeeks() { return seeks; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof CursorStats)) return false; + CursorStats that = (CursorStats) o; + return Objects.equals(properties, that.properties) && Objects.equals(writesExecuted, that.writesExecuted) && Objects.equals(writesIgnored, that.writesIgnored) && Objects.equals(scannedFull, that.scannedFull) && Objects.equals(scannedIndex, that.scannedIndex) && Objects.equals(cursorsCreated, that.cursorsCreated) && Objects.equals(cursorsRearmed, that.cursorsRearmed) && Objects.equals(cacheHits, that.cacheHits) && Objects.equals(cacheMisses, that.cacheMisses) && Objects.equals(filtered, that.filtered) && Objects.equals(httpRequests, that.httpRequests) && Objects.equals(fullCount, that.fullCount) && Objects.equals(executionTime, that.executionTime) && Objects.equals(peakMemoryUsage, that.peakMemoryUsage) && Objects.equals(documentLookups, that.documentLookups) && Objects.equals(intermediateCommits, that.intermediateCommits) && Objects.equals(seeks, that.seeks); + } + + @Override + public int hashCode() { + return Objects.hash(properties, writesExecuted, writesIgnored, scannedFull, scannedIndex, cursorsCreated, cursorsRearmed, cacheHits, cacheMisses, filtered, httpRequests, fullCount, executionTime, peakMemoryUsage, documentLookups, intermediateCommits, seeks); + } } diff --git a/core/src/main/java/com/arangodb/entity/CursorWarning.java b/core/src/main/java/com/arangodb/entity/CursorWarning.java index 72dc8ff1c..96d541efe 100644 --- a/core/src/main/java/com/arangodb/entity/CursorWarning.java +++ b/core/src/main/java/com/arangodb/entity/CursorWarning.java @@ -1,5 +1,7 @@ package com.arangodb.entity; +import java.util.Objects; + public final class CursorWarning { private Integer code; @@ -13,4 +15,15 @@ public String getMessage() { return message; } + @Override + public boolean equals(Object o) { + if (!(o instanceof CursorWarning)) return false; + CursorWarning that = (CursorWarning) o; + return Objects.equals(code, that.code) && Objects.equals(message, that.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, message); + } } diff --git a/core/src/main/java/com/arangodb/entity/DatabaseEntity.java b/core/src/main/java/com/arangodb/entity/DatabaseEntity.java index 97005edef..73df87062 100644 --- a/core/src/main/java/com/arangodb/entity/DatabaseEntity.java +++ b/core/src/main/java/com/arangodb/entity/DatabaseEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -92,4 +94,16 @@ public Integer getWriteConcern() { public String getSharding() { return sharding; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof DatabaseEntity)) return false; + DatabaseEntity that = (DatabaseEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(path, that.path) && Objects.equals(isSystem, that.isSystem) && Objects.equals(replicationFactor, that.replicationFactor) && Objects.equals(writeConcern, that.writeConcern) && Objects.equals(sharding, that.sharding); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, path, isSystem, replicationFactor, writeConcern, sharding); + } } diff --git a/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index 0eeff2cf9..c5329e95c 100644 --- a/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -22,6 +22,8 @@ import com.arangodb.internal.serde.UserData; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -59,4 +61,16 @@ public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } + @Override + public boolean equals(Object o) { + if (!(o instanceof DocumentCreateEntity)) return false; + if (!super.equals(o)) return false; + DocumentCreateEntity that = (DocumentCreateEntity) o; + return Objects.equals(newDocument, that.newDocument) && Objects.equals(oldDocument, that.oldDocument); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), newDocument, oldDocument); + } } diff --git a/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index fac6c36ae..41674fdbe 100644 --- a/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -22,6 +22,8 @@ import com.arangodb.internal.serde.UserData; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -45,4 +47,17 @@ public T getOld() { public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof DocumentDeleteEntity)) return false; + if (!super.equals(o)) return false; + DocumentDeleteEntity that = (DocumentDeleteEntity) o; + return Objects.equals(oldDocument, that.oldDocument); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), oldDocument); + } } diff --git a/core/src/main/java/com/arangodb/entity/DocumentEntity.java b/core/src/main/java/com/arangodb/entity/DocumentEntity.java index 56cc8545b..c0f82bd27 100644 --- a/core/src/main/java/com/arangodb/entity/DocumentEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentEntity.java @@ -23,6 +23,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -56,4 +58,15 @@ public String getRev() { return rev; } + @Override + public boolean equals(Object o) { + if (!(o instanceof DocumentEntity)) return false; + DocumentEntity that = (DocumentEntity) o; + return Objects.equals(key, that.key) && Objects.equals(id, that.id) && Objects.equals(rev, that.rev); + } + + @Override + public int hashCode() { + return Objects.hash(key, id, rev); + } } diff --git a/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java b/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java index b4f6a469f..eb7d48f18 100644 --- a/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -108,4 +109,15 @@ public void setDetails(final Collection details) { this.details = details; } + @Override + public boolean equals(Object o) { + if (!(o instanceof DocumentImportEntity)) return false; + DocumentImportEntity that = (DocumentImportEntity) o; + return Objects.equals(created, that.created) && Objects.equals(errors, that.errors) && Objects.equals(empty, that.empty) && Objects.equals(updated, that.updated) && Objects.equals(ignored, that.ignored) && Objects.equals(details, that.details); + } + + @Override + public int hashCode() { + return Objects.hash(created, errors, empty, updated, ignored, details); + } } diff --git a/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index d98ee7e56..2a0a3b6c2 100644 --- a/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -23,6 +23,8 @@ import com.arangodb.internal.serde.UserData; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -66,4 +68,16 @@ public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } + @Override + public boolean equals(Object o) { + if (!(o instanceof DocumentUpdateEntity)) return false; + if (!super.equals(o)) return false; + DocumentUpdateEntity that = (DocumentUpdateEntity) o; + return Objects.equals(oldRev, that.oldRev) && Objects.equals(newDocument, that.newDocument) && Objects.equals(oldDocument, that.oldDocument); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), oldRev, newDocument, oldDocument); + } } diff --git a/core/src/main/java/com/arangodb/entity/EdgeDefinition.java b/core/src/main/java/com/arangodb/entity/EdgeDefinition.java index 980fc05bc..b89f67417 100644 --- a/core/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/core/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Objects; /** * @author Mark Vollmary @@ -80,11 +81,35 @@ public EdgeDefinition satellites(final String... satellites) { return this; } + @Override + public boolean equals(Object o) { + if (!(o instanceof EdgeDefinition)) return false; + EdgeDefinition that = (EdgeDefinition) o; + return Objects.equals(collection, that.collection) && Objects.equals(from, that.from) && Objects.equals(to, that.to) && Objects.equals(options, that.options); + } + + @Override + public int hashCode() { + return Objects.hash(collection, from, to, options); + } + public static final class Options { private Collection satellites = Collections.emptyList(); public Collection getSatellites() { return satellites; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Options)) return false; + Options options = (Options) o; + return Objects.equals(satellites, options.satellites); + } + + @Override + public int hashCode() { + return Objects.hashCode(satellites); + } } } diff --git a/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index 6a5cb5a9a..15666c91d 100644 --- a/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -22,6 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -38,4 +40,16 @@ public String getOldRev() { return oldRev; } + @Override + public boolean equals(Object o) { + if (!(o instanceof EdgeUpdateEntity)) return false; + if (!super.equals(o)) return false; + EdgeUpdateEntity that = (EdgeUpdateEntity) o; + return Objects.equals(oldRev, that.oldRev); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), oldRev); + } } diff --git a/core/src/main/java/com/arangodb/entity/ErrorEntity.java b/core/src/main/java/com/arangodb/entity/ErrorEntity.java index 5677d2301..534a70ecf 100644 --- a/core/src/main/java/com/arangodb/entity/ErrorEntity.java +++ b/core/src/main/java/com/arangodb/entity/ErrorEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import java.io.Serializable; +import java.util.Objects; /** * @author Mark Vollmary @@ -66,4 +67,15 @@ public int getErrorNum() { return errorNum; } + @Override + public boolean equals(Object o) { + if (!(o instanceof ErrorEntity)) return false; + ErrorEntity that = (ErrorEntity) o; + return code == that.code && errorNum == that.errorNum && Objects.equals(errorMessage, that.errorMessage) && Objects.equals(exception, that.exception); + } + + @Override + public int hashCode() { + return Objects.hash(errorMessage, exception, code, errorNum); + } } diff --git a/core/src/main/java/com/arangodb/entity/GraphEntity.java b/core/src/main/java/com/arangodb/entity/GraphEntity.java index dce443d60..9a068c566 100644 --- a/core/src/main/java/com/arangodb/entity/GraphEntity.java +++ b/core/src/main/java/com/arangodb/entity/GraphEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -129,4 +130,16 @@ public String getSmartGraphAttribute() { public Boolean getIsSatellite() { return isSatellite; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof GraphEntity)) return false; + GraphEntity that = (GraphEntity) o; + return Objects.equals(name, that.name) && Objects.equals(edgeDefinitions, that.edgeDefinitions) && Objects.equals(orphanCollections, that.orphanCollections) && Objects.equals(numberOfShards, that.numberOfShards) && Objects.equals(_id, that._id) && Objects.equals(_rev, that._rev) && Objects.equals(replicationFactor, that.replicationFactor) && Objects.equals(writeConcern, that.writeConcern) && Objects.equals(isSmart, that.isSmart) && Objects.equals(isDisjoint, that.isDisjoint) && Objects.equals(smartGraphAttribute, that.smartGraphAttribute) && Objects.equals(isSatellite, that.isSatellite); + } + + @Override + public int hashCode() { + return Objects.hash(name, edgeDefinitions, orphanCollections, numberOfShards, _id, _rev, replicationFactor, writeConcern, isSmart, isDisjoint, smartGraphAttribute, isSatellite); + } } diff --git a/core/src/main/java/com/arangodb/entity/IndexEntity.java b/core/src/main/java/com/arangodb/entity/IndexEntity.java index b488845b7..cbf1140bb 100644 --- a/core/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/core/src/main/java/com/arangodb/entity/IndexEntity.java @@ -23,6 +23,7 @@ import com.arangodb.model.MDIFieldValueTypes; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -133,4 +134,16 @@ public MDIFieldValueTypes getFieldValueTypes() { public Collection getPrefixFields() { return prefixFields; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IndexEntity)) return false; + IndexEntity that = (IndexEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) && type == that.type && Objects.equals(fields, that.fields) && Objects.equals(selectivityEstimate, that.selectivityEstimate) && Objects.equals(unique, that.unique) && Objects.equals(sparse, that.sparse) && Objects.equals(minLength, that.minLength) && Objects.equals(isNewlyCreated, that.isNewlyCreated) && Objects.equals(geoJson, that.geoJson) && Objects.equals(constraint, that.constraint) && Objects.equals(deduplicate, that.deduplicate) && Objects.equals(expireAfter, that.expireAfter) && Objects.equals(inBackground, that.inBackground) && Objects.equals(estimates, that.estimates) && Objects.equals(cacheEnabled, that.cacheEnabled) && Objects.equals(storedValues, that.storedValues) && Objects.equals(legacyPolygons, that.legacyPolygons) && fieldValueTypes == that.fieldValueTypes && Objects.equals(prefixFields, that.prefixFields); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, type, fields, selectivityEstimate, unique, sparse, minLength, isNewlyCreated, geoJson, constraint, deduplicate, expireAfter, inBackground, estimates, cacheEnabled, storedValues, legacyPolygons, fieldValueTypes, prefixFields); + } } diff --git a/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java index 110f21ab9..102d96fbe 100644 --- a/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java +++ b/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java @@ -25,6 +25,7 @@ import com.arangodb.entity.arangosearch.StoredValue; import java.util.Collection; +import java.util.Objects; import java.util.Set; /** @@ -163,4 +164,16 @@ public Boolean getCache() { public Boolean getPrimaryKeyCache() { return primaryKeyCache; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof InvertedIndexEntity)) return false; + InvertedIndexEntity that = (InvertedIndexEntity) o; + return Objects.equals(id, that.id) && Objects.equals(isNewlyCreated, that.isNewlyCreated) && Objects.equals(unique, that.unique) && Objects.equals(sparse, that.sparse) && Objects.equals(version, that.version) && Objects.equals(code, that.code) && type == that.type && Objects.equals(name, that.name) && Objects.equals(fields, that.fields) && Objects.equals(searchField, that.searchField) && Objects.equals(storedValues, that.storedValues) && Objects.equals(optimizeTopK, that.optimizeTopK) && Objects.equals(primarySort, that.primarySort) && Objects.equals(analyzer, that.analyzer) && Objects.equals(features, that.features) && Objects.equals(includeAllFields, that.includeAllFields) && Objects.equals(trackListPositions, that.trackListPositions) && Objects.equals(cleanupIntervalStep, that.cleanupIntervalStep) && Objects.equals(commitIntervalMsec, that.commitIntervalMsec) && Objects.equals(consolidationIntervalMsec, that.consolidationIntervalMsec) && Objects.equals(consolidationPolicy, that.consolidationPolicy) && Objects.equals(writebufferIdle, that.writebufferIdle) && Objects.equals(writebufferActive, that.writebufferActive) && Objects.equals(writebufferSizeMax, that.writebufferSizeMax) && Objects.equals(cache, that.cache) && Objects.equals(primaryKeyCache, that.primaryKeyCache); + } + + @Override + public int hashCode() { + return Objects.hash(id, isNewlyCreated, unique, sparse, version, code, type, name, fields, searchField, storedValues, optimizeTopK, primarySort, analyzer, features, includeAllFields, trackListPositions, cleanupIntervalStep, commitIntervalMsec, consolidationIntervalMsec, consolidationPolicy, writebufferIdle, writebufferActive, writebufferSizeMax, cache, primaryKeyCache); + } } diff --git a/core/src/main/java/com/arangodb/entity/KeyOptions.java b/core/src/main/java/com/arangodb/entity/KeyOptions.java index 7206c9dbb..dbeb87d8c 100644 --- a/core/src/main/java/com/arangodb/entity/KeyOptions.java +++ b/core/src/main/java/com/arangodb/entity/KeyOptions.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -74,4 +76,15 @@ public void setOffset(final Integer offset) { this.offset = offset; } + @Override + public boolean equals(Object o) { + if (!(o instanceof KeyOptions)) return false; + KeyOptions that = (KeyOptions) o; + return Objects.equals(allowUserKeys, that.allowUserKeys) && type == that.type && Objects.equals(increment, that.increment) && Objects.equals(offset, that.offset); + } + + @Override + public int hashCode() { + return Objects.hash(allowUserKeys, type, increment, offset); + } } diff --git a/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java b/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java index a78a3f93d..9622525b1 100644 --- a/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java +++ b/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import java.util.List; +import java.util.Objects; /** * @author Michele Rastelli @@ -39,6 +40,18 @@ public List getMessages() { return messages; } + @Override + public boolean equals(Object o) { + if (!(o instanceof LogEntriesEntity)) return false; + LogEntriesEntity that = (LogEntriesEntity) o; + return Objects.equals(total, that.total) && Objects.equals(messages, that.messages); + } + + @Override + public int hashCode() { + return Objects.hash(total, messages); + } + public static final class Message { Long id; String topic; @@ -65,6 +78,18 @@ public String getDate() { public String getMessage() { return message; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Message)) return false; + Message message1 = (Message) o; + return Objects.equals(id, message1.id) && Objects.equals(topic, message1.topic) && Objects.equals(level, message1.level) && Objects.equals(date, message1.date) && Objects.equals(message, message1.message); + } + + @Override + public int hashCode() { + return Objects.hash(id, topic, level, date, message); + } } } diff --git a/core/src/main/java/com/arangodb/entity/LogLevelEntity.java b/core/src/main/java/com/arangodb/entity/LogLevelEntity.java index 39daaf59b..a12372749 100644 --- a/core/src/main/java/com/arangodb/entity/LogLevelEntity.java +++ b/core/src/main/java/com/arangodb/entity/LogLevelEntity.java @@ -22,6 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -466,6 +468,18 @@ public void setGeneral(LogLevel general) { this.general = general; } + @Override + public boolean equals(Object o) { + if (!(o instanceof LogLevelEntity)) return false; + LogLevelEntity that = (LogLevelEntity) o; + return all == that.all && agency == that.agency && agencycomm == that.agencycomm && agencystore == that.agencystore && backup == that.backup && bench == that.bench && cluster == that.cluster && communication == that.communication && authentication == that.authentication && config == that.config && crash == that.crash && dump == that.dump && engines == that.engines && cache == that.cache && security == that.security && startup == that.startup && trx == that.trx && supervision == that.supervision && threads == that.threads && ttl == that.ttl && ssl == that.ssl && replication2 == that.replication2 && restore == that.restore && memory == that.memory && validation == that.validation && statistics == that.statistics && v8 == that.v8 && syscall == that.syscall && libiresearch == that.libiresearch && license == that.license && deprecation == that.deprecation && rocksdb == that.rocksdb && requests == that.requests && repWal == that.repWal && arangosearch == that.arangosearch && views == that.views && repState == that.repState && authorization == that.authorization && queries == that.queries && aql == that.aql && graphs == that.graphs && maintenance == that.maintenance && development == that.development && replication == that.replication && httpclient == that.httpclient && heartbeat == that.heartbeat && flush == that.flush && general == that.general; + } + + @Override + public int hashCode() { + return Objects.hash(all, agency, agencycomm, agencystore, backup, bench, cluster, communication, authentication, config, crash, dump, engines, cache, security, startup, trx, supervision, threads, ttl, ssl, replication2, restore, memory, validation, statistics, v8, syscall, libiresearch, license, deprecation, rocksdb, requests, repWal, arangosearch, views, repState, authorization, queries, aql, graphs, maintenance, development, replication, httpclient, heartbeat, flush, general); + } + public enum LogLevel { FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DEFAULT } diff --git a/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java b/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java index 6bdbe2873..14c899702 100644 --- a/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java +++ b/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * @author Mark Vollmary @@ -81,4 +82,16 @@ public Boolean isPotentialDirtyRead() { public void setPotentialDirtyRead(final Boolean isPotentialDirtyRead) { this.isPotentialDirtyRead = isPotentialDirtyRead; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof MultiDocumentEntity)) return false; + MultiDocumentEntity that = (MultiDocumentEntity) o; + return isPotentialDirtyRead == that.isPotentialDirtyRead && Objects.equals(documents, that.documents) && Objects.equals(errors, that.errors) && Objects.equals(documentsAndErrors, that.documentsAndErrors); + } + + @Override + public int hashCode() { + return Objects.hash(documents, errors, documentsAndErrors, isPotentialDirtyRead); + } } diff --git a/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java index 83efee47b..83758e581 100644 --- a/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -60,6 +62,18 @@ public void setMaxResults(final Long maxResults) { this.maxResults = maxResults; } + @Override + public boolean equals(Object o) { + if (!(o instanceof QueryCachePropertiesEntity)) return false; + QueryCachePropertiesEntity that = (QueryCachePropertiesEntity) o; + return mode == that.mode && Objects.equals(maxResults, that.maxResults); + } + + @Override + public int hashCode() { + return Objects.hash(mode, maxResults); + } + public enum CacheMode { off, on, demand } diff --git a/core/src/main/java/com/arangodb/entity/QueryEntity.java b/core/src/main/java/com/arangodb/entity/QueryEntity.java index 0965bf33a..9518f5fe4 100644 --- a/core/src/main/java/com/arangodb/entity/QueryEntity.java +++ b/core/src/main/java/com/arangodb/entity/QueryEntity.java @@ -22,6 +22,7 @@ import java.util.Date; import java.util.Map; +import java.util.Objects; /** * @author Mark Vollmary @@ -108,4 +109,16 @@ public QueryExecutionState getState() { public Boolean getStream() { return stream; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof QueryEntity)) return false; + QueryEntity that = (QueryEntity) o; + return Objects.equals(id, that.id) && Objects.equals(database, that.database) && Objects.equals(user, that.user) && Objects.equals(query, that.query) && Objects.equals(bindVars, that.bindVars) && Objects.equals(started, that.started) && Objects.equals(runTime, that.runTime) && Objects.equals(peakMemoryUsage, that.peakMemoryUsage) && state == that.state && Objects.equals(stream, that.stream); + } + + @Override + public int hashCode() { + return Objects.hash(id, database, user, query, bindVars, started, runTime, peakMemoryUsage, state, stream); + } } diff --git a/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java b/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java index e6b543a6d..ef7068af6 100644 --- a/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java +++ b/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java @@ -1,5 +1,7 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @since ArangoDB 3.10 */ @@ -15,6 +17,18 @@ public Flags getFlags() { return flags; } + @Override + public boolean equals(Object o) { + if (!(o instanceof QueryOptimizerRule)) return false; + QueryOptimizerRule that = (QueryOptimizerRule) o; + return Objects.equals(name, that.name) && Objects.equals(flags, that.flags); + } + + @Override + public int hashCode() { + return Objects.hash(name, flags); + } + public static class Flags { private Boolean hidden; private Boolean clusterOnly; @@ -46,5 +60,17 @@ public Boolean getDisabledByDefault() { public Boolean getEnterpriseOnly() { return enterpriseOnly; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Flags)) return false; + Flags flags = (Flags) o; + return Objects.equals(hidden, flags.hidden) && Objects.equals(clusterOnly, flags.clusterOnly) && Objects.equals(canBeDisabled, flags.canBeDisabled) && Objects.equals(canCreateAdditionalPlans, flags.canCreateAdditionalPlans) && Objects.equals(disabledByDefault, flags.disabledByDefault) && Objects.equals(enterpriseOnly, flags.enterpriseOnly); + } + + @Override + public int hashCode() { + return Objects.hash(hidden, clusterOnly, canBeDisabled, canCreateAdditionalPlans, disabledByDefault, enterpriseOnly); + } } } diff --git a/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java index 80fb242de..52378b408 100644 --- a/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -129,4 +131,15 @@ public void setMaxQueryStringLength(final Long maxQueryStringLength) { this.maxQueryStringLength = maxQueryStringLength; } + @Override + public boolean equals(Object o) { + if (!(o instanceof QueryTrackingPropertiesEntity)) return false; + QueryTrackingPropertiesEntity that = (QueryTrackingPropertiesEntity) o; + return Objects.equals(enabled, that.enabled) && Objects.equals(trackSlowQueries, that.trackSlowQueries) && Objects.equals(maxSlowQueries, that.maxSlowQueries) && Objects.equals(slowQueryThreshold, that.slowQueryThreshold) && Objects.equals(maxQueryStringLength, that.maxQueryStringLength); + } + + @Override + public int hashCode() { + return Objects.hash(enabled, trackSlowQueries, maxSlowQueries, slowQueryThreshold, maxQueryStringLength); + } } diff --git a/core/src/main/java/com/arangodb/entity/ShardEntity.java b/core/src/main/java/com/arangodb/entity/ShardEntity.java index 8b853a623..8ba767816 100644 --- a/core/src/main/java/com/arangodb/entity/ShardEntity.java +++ b/core/src/main/java/com/arangodb/entity/ShardEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Michele Rastelli */ @@ -35,4 +37,15 @@ public String getShardId() { return shardId; } + @Override + public boolean equals(Object o) { + if (!(o instanceof ShardEntity)) return false; + ShardEntity that = (ShardEntity) o; + return Objects.equals(shardId, that.shardId); + } + + @Override + public int hashCode() { + return Objects.hashCode(shardId); + } } diff --git a/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java b/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java index 82dd79c7b..674babd71 100644 --- a/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java +++ b/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Michele Rastelli * @since ArangoDB 3.5.0 @@ -37,4 +39,15 @@ public StreamTransactionStatus getStatus() { return status; } + @Override + public boolean equals(Object o) { + if (!(o instanceof StreamTransactionEntity)) return false; + StreamTransactionEntity that = (StreamTransactionEntity) o; + return Objects.equals(id, that.id) && status == that.status; + } + + @Override + public int hashCode() { + return Objects.hash(id, status); + } } diff --git a/core/src/main/java/com/arangodb/entity/TransactionEntity.java b/core/src/main/java/com/arangodb/entity/TransactionEntity.java index 2161c5766..043c22819 100644 --- a/core/src/main/java/com/arangodb/entity/TransactionEntity.java +++ b/core/src/main/java/com/arangodb/entity/TransactionEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Michele Rastelli * @since ArangoDB 3.5.0 @@ -37,4 +39,15 @@ public StreamTransactionStatus getState() { return state; } + @Override + public boolean equals(Object o) { + if (!(o instanceof TransactionEntity)) return false; + TransactionEntity that = (TransactionEntity) o; + return Objects.equals(id, that.id) && state == that.state; + } + + @Override + public int hashCode() { + return Objects.hash(id, state); + } } diff --git a/core/src/main/java/com/arangodb/entity/UserEntity.java b/core/src/main/java/com/arangodb/entity/UserEntity.java index 76181ffe4..64b213439 100644 --- a/core/src/main/java/com/arangodb/entity/UserEntity.java +++ b/core/src/main/java/com/arangodb/entity/UserEntity.java @@ -21,6 +21,7 @@ package com.arangodb.entity; import java.util.Map; +import java.util.Objects; /** * @author Mark Vollmary @@ -57,4 +58,15 @@ public Boolean getChangePassword() { return changePassword; } + @Override + public boolean equals(Object o) { + if (!(o instanceof UserEntity)) return false; + UserEntity that = (UserEntity) o; + return Objects.equals(user, that.user) && Objects.equals(active, that.active) && Objects.equals(extra, that.extra) && Objects.equals(changePassword, that.changePassword); + } + + @Override + public int hashCode() { + return Objects.hash(user, active, extra, changePassword); + } } diff --git a/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index ef19a4386..22c2f0853 100644 --- a/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -22,6 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -38,4 +40,16 @@ public String getOldRev() { return oldRev; } + @Override + public boolean equals(Object o) { + if (!(o instanceof VertexUpdateEntity)) return false; + if (!super.equals(o)) return false; + VertexUpdateEntity that = (VertexUpdateEntity) o; + return Objects.equals(oldRev, that.oldRev); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), oldRev); + } } diff --git a/core/src/main/java/com/arangodb/entity/ViewEntity.java b/core/src/main/java/com/arangodb/entity/ViewEntity.java index e5eb28299..94c7e0a6d 100644 --- a/core/src/main/java/com/arangodb/entity/ViewEntity.java +++ b/core/src/main/java/com/arangodb/entity/ViewEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import java.util.Objects; + /** * @author Mark Vollmary */ @@ -52,4 +54,15 @@ public ViewType getType() { return type; } + @Override + public boolean equals(Object o) { + if (!(o instanceof ViewEntity)) return false; + ViewEntity that = (ViewEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) && type == that.type; + } + + @Override + public int hashCode() { + return Objects.hash(id, name, type); + } } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index 5255a3fff..fa729e1e0 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -136,4 +137,17 @@ public Boolean getPrimarySortCache() { public Boolean getPrimaryKeyCache() { return primaryKeyCache; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ArangoSearchPropertiesEntity)) return false; + if (!super.equals(o)) return false; + ArangoSearchPropertiesEntity that = (ArangoSearchPropertiesEntity) o; + return Objects.equals(consolidationIntervalMsec, that.consolidationIntervalMsec) && Objects.equals(commitIntervalMsec, that.commitIntervalMsec) && Objects.equals(cleanupIntervalStep, that.cleanupIntervalStep) && Objects.equals(consolidationPolicy, that.consolidationPolicy) && Objects.equals(primarySort, that.primarySort) && Objects.equals(links, that.links) && primarySortCompression == that.primarySortCompression && Objects.equals(storedValues, that.storedValues) && Objects.equals(optimizeTopK, that.optimizeTopK) && Objects.equals(primarySortCache, that.primarySortCache) && Objects.equals(primaryKeyCache, that.primaryKeyCache); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), consolidationIntervalMsec, commitIntervalMsec, cleanupIntervalStep, consolidationPolicy, primarySort, links, primarySortCompression, storedValues, optimizeTopK, primarySortCache, primaryKeyCache); + } } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index c5901abcc..eb33ebb20 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -30,6 +30,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Objects; /** * @author Mark Vollmary @@ -188,4 +189,15 @@ public Boolean getCache() { return cache; } + @Override + public boolean equals(Object o) { + if (!(o instanceof CollectionLink)) return false; + CollectionLink that = (CollectionLink) o; + return Objects.equals(name, that.name) && Objects.equals(analyzers, that.analyzers) && Objects.equals(includeAllFields, that.includeAllFields) && Objects.equals(trackListPositions, that.trackListPositions) && storeValues == that.storeValues && Objects.equals(fields, that.fields) && Objects.equals(nested, that.nested) && Objects.equals(inBackground, that.inBackground) && Objects.equals(cache, that.cache); + } + + @Override + public int hashCode() { + return Objects.hash(name, analyzers, includeAllFields, trackListPositions, storeValues, fields, nested, inBackground, cache); + } } \ No newline at end of file diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java index 730996084..1d2f0f8f8 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -10,6 +10,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Objects; public final class FieldLink { @@ -164,4 +165,16 @@ public Boolean getInBackground() { public Boolean getCache() { return cache; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof FieldLink)) return false; + FieldLink fieldLink = (FieldLink) o; + return Objects.equals(name, fieldLink.name) && Objects.equals(analyzers, fieldLink.analyzers) && Objects.equals(includeAllFields, fieldLink.includeAllFields) && Objects.equals(trackListPositions, fieldLink.trackListPositions) && storeValues == fieldLink.storeValues && Objects.equals(fields, fieldLink.fields) && Objects.equals(nested, fieldLink.nested) && Objects.equals(inBackground, fieldLink.inBackground) && Objects.equals(cache, fieldLink.cache); + } + + @Override + public int hashCode() { + return Objects.hash(name, analyzers, includeAllFields, trackListPositions, storeValues, fields, nested, inBackground, cache); + } } \ No newline at end of file diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java b/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java index 742b1d088..10b054108 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java @@ -23,6 +23,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Heiko Kernbach */ @@ -86,4 +88,16 @@ public enum Direction { asc, desc } + + @Override + public boolean equals(Object o) { + if (!(o instanceof PrimarySort)) return false; + PrimarySort that = (PrimarySort) o; + return Objects.equals(fieldName, that.fieldName) && Objects.equals(ascending, that.ascending); + } + + @Override + public int hashCode() { + return Objects.hash(fieldName, ascending); + } } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java index 1d18076f0..7d92d2768 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + /** * @author Michele Rastelli * @since ArabgoDB 3.10 @@ -50,4 +52,16 @@ public OperationType getOperation() { public enum OperationType { add, del } + + @Override + public boolean equals(Object o) { + if (!(o instanceof SearchAliasIndex)) return false; + SearchAliasIndex that = (SearchAliasIndex) o; + return Objects.equals(collection, that.collection) && Objects.equals(index, that.index) && operation == that.operation; + } + + @Override + public int hashCode() { + return Objects.hash(collection, index, operation); + } } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java index 6a0664214..208c17664 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Objects; /** * @author Michele Rastelli @@ -39,4 +40,16 @@ public Collection getIndexes() { return indexes; } + @Override + public boolean equals(Object o) { + if (!(o instanceof SearchAliasPropertiesEntity)) return false; + if (!super.equals(o)) return false; + SearchAliasPropertiesEntity that = (SearchAliasPropertiesEntity) o; + return Objects.equals(indexes, that.indexes); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), indexes); + } } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index 4716f5864..d300b7f99 100644 --- a/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -73,8 +73,7 @@ public Boolean getCache() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof StoredValue)) return false; StoredValue that = (StoredValue) o; return Objects.equals(fields, that.fields) && compression == that.compression && Objects.equals(cache, that.cache); } diff --git a/core/src/main/java/com/arangodb/internal/ArangoDefaults.java b/core/src/main/java/com/arangodb/internal/ArangoDefaults.java index b08c045da..25448187c 100644 --- a/core/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/core/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -50,6 +50,7 @@ public final class ArangoDefaults { public static final Boolean DEFAULT_USE_SSL = false; public static final Boolean DEFAULT_VERIFY_HOST = true; public static final Integer DEFAULT_CHUNK_SIZE = 30_000; + public static final Boolean DEFAULT_PIPELINING = false; public static final Boolean DEFAULT_ACQUIRE_HOST_LIST = false; public static final Integer DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; diff --git a/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java b/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java index f38903532..f95e0a4e2 100644 --- a/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java +++ b/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java @@ -33,6 +33,7 @@ public class ArangoConfig { private SSLContext sslContext; private Boolean verifyHost; private Integer chunkSize; + private Boolean pipelining; private Integer maxConnections; private Long connectionTtl; private Integer keepAliveInterval; @@ -70,6 +71,7 @@ public void loadProperties(final ArangoConfigProperties properties) { useSsl = properties.getUseSsl().orElse(ArangoDefaults.DEFAULT_USE_SSL); verifyHost = properties.getVerifyHost().orElse(ArangoDefaults.DEFAULT_VERIFY_HOST); chunkSize = properties.getChunkSize().orElse(ArangoDefaults.DEFAULT_CHUNK_SIZE); + pipelining = properties.getPipelining().orElse(ArangoDefaults.DEFAULT_PIPELINING); // FIXME: make maxConnections field Optional maxConnections = properties.getMaxConnections().orElse(null); // FIXME: make connectionTtl field Optional @@ -173,6 +175,14 @@ public void setChunkSize(Integer chunkSize) { this.chunkSize = chunkSize; } + public Boolean getPipelining() { + return pipelining; + } + + public void setPipelining(Boolean pipelining) { + this.pipelining = pipelining; + } + public Integer getMaxConnections() { if (maxConnections == null) { maxConnections = getDefaultMaxConnections(); diff --git a/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java b/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java index 2200db752..f7d865f81 100644 --- a/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java +++ b/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java @@ -68,7 +68,7 @@ private String getProperty(String key) { @Override public Optional> getHosts() { - return Optional.ofNullable(getProperty("hosts")) + return Optional.ofNullable(getProperty(KEY_HOSTS)) .map(s -> { List hostDescriptions = new ArrayList<>(); String[] hosts = s.split(","); @@ -81,97 +81,109 @@ public Optional> getHosts() { @Override public Optional getProtocol() { - return Optional.ofNullable(getProperty("protocol")).map(Protocol::valueOf); + return Optional.ofNullable(getProperty(KEY_PROTOCOL)).map(Protocol::valueOf); } @Override public Optional getUser() { - return Optional.ofNullable(getProperty("user")); + return Optional.ofNullable(getProperty(KEY_USER)); } @Override public Optional getPassword() { - return Optional.ofNullable(getProperty("password")); + return Optional.ofNullable(getProperty(KEY_PASSWORD)); } @Override public Optional getJwt() { - return Optional.ofNullable(getProperty("jwt")); + return Optional.ofNullable(getProperty(KEY_JWT)); } @Override public Optional getTimeout() { - return Optional.ofNullable(getProperty("timeout")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_TIMEOUT)).map(Integer::valueOf); } @Override public Optional getUseSsl() { - return Optional.ofNullable(getProperty("useSsl")).map(Boolean::valueOf); + return Optional.ofNullable(getProperty(KEY_USE_SSL)).map(Boolean::valueOf); } @Override public Optional getVerifyHost() { - return Optional.ofNullable(getProperty("verifyHost")).map(Boolean::valueOf); + return Optional.ofNullable(getProperty(KEY_VERIFY_HOST)).map(Boolean::valueOf); } @Override public Optional getChunkSize() { - return Optional.ofNullable(getProperty("chunkSize")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_CHUNK_SIZE)).map(Integer::valueOf); + } + + @Override + public Optional getPipelining() { + return Optional.ofNullable(getProperty(KEY_PIPELINING)).map(Boolean::valueOf); } @Override public Optional getMaxConnections() { - return Optional.ofNullable(getProperty("maxConnections")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_MAX_CONNECTIONS)).map(Integer::valueOf); } @Override public Optional getConnectionTtl() { - return Optional.ofNullable(getProperty("connectionTtl")).map(Long::valueOf); + return Optional.ofNullable(getProperty(KEY_CONNECTION_TTL)).map(Long::valueOf); } @Override public Optional getKeepAliveInterval() { - return Optional.ofNullable(getProperty("keepAliveInterval")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_KEEP_ALIVE_INTERVAL)).map(Integer::valueOf); } @Override public Optional getAcquireHostList() { - return Optional.ofNullable(getProperty("acquireHostList")).map(Boolean::valueOf); + return Optional.ofNullable(getProperty(KEY_ACQUIRE_HOST_LIST)).map(Boolean::valueOf); } @Override public Optional getAcquireHostListInterval() { - return Optional.ofNullable(getProperty("acquireHostListInterval")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_ACQUIRE_HOST_LIST_INTERVAL)).map(Integer::valueOf); } @Override public Optional getLoadBalancingStrategy() { - return Optional.ofNullable(getProperty("loadBalancingStrategy")).map(LoadBalancingStrategy::valueOf); + return Optional.ofNullable(getProperty(KEY_LOAD_BALANCING_STRATEGY)).map(LoadBalancingStrategy::valueOf); } @Override public Optional getResponseQueueTimeSamples() { - return Optional.ofNullable(getProperty("responseQueueTimeSamples")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_RESPONSE_QUEUE_TIME_SAMPLES)).map(Integer::valueOf); } @Override public Optional getCompression() { - return Optional.ofNullable(getProperty("compression")).map(Compression::valueOf); + return Optional.ofNullable(getProperty(KEY_COMPRESSION)).map(Compression::valueOf); } @Override public Optional getCompressionThreshold() { - return Optional.ofNullable(getProperty("compressionThreshold")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_COMPRESSION_THRESHOLD)).map(Integer::valueOf); } @Override public Optional getCompressionLevel() { - return Optional.ofNullable(getProperty("compressionLevel")).map(Integer::valueOf); + return Optional.ofNullable(getProperty(KEY_COMPRESSION_LEVEL)).map(Integer::valueOf); } @Override public Optional getSerdeProviderClass() { - return Optional.ofNullable(getProperty("serdeProviderClass")); + return Optional.ofNullable(getProperty(KEY_SERDE_PROVIDER_CLASS)); } + @Override + public String toString() { + return "ArangoConfigPropertiesImpl{" + + "prefix='" + prefix + '\'' + + ", properties=" + properties + + '}'; + } } diff --git a/core/src/main/java/com/arangodb/internal/net/Communication.java b/core/src/main/java/com/arangodb/internal/net/Communication.java index 0309cd04c..26251e33d 100644 --- a/core/src/main/java/com/arangodb/internal/net/Communication.java +++ b/core/src/main/java/com/arangodb/internal/net/Communication.java @@ -50,7 +50,9 @@ public CompletableFuture executeAsync(final InternalRequest re private CompletableFuture executeAsync(final InternalRequest request, final HostHandle hostHandle, final Host host, final int attemptCount) { long reqId = reqCount.getAndIncrement(); - return doExecuteAsync(request, hostHandle, host, attemptCount, host.connection(), reqId); + return host.connection().thenCompose(c -> + doExecuteAsync(request, hostHandle, host, attemptCount, c, reqId) + .whenComplete((r, t) -> c.release())); } private CompletableFuture doExecuteAsync( diff --git a/core/src/main/java/com/arangodb/internal/net/Connection.java b/core/src/main/java/com/arangodb/internal/net/Connection.java index b092448d3..461c5ccea 100644 --- a/core/src/main/java/com/arangodb/internal/net/Connection.java +++ b/core/src/main/java/com/arangodb/internal/net/Connection.java @@ -35,4 +35,6 @@ public interface Connection extends Closeable { void setJwt(String jwt); CompletableFuture executeAsync(InternalRequest request); + + void release(); } diff --git a/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java b/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java index b0fbbdf7b..0e01ca824 100644 --- a/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java @@ -29,5 +29,5 @@ */ @UsedInApi public interface ConnectionFactory { - Connection create(ArangoConfig config, HostDescription host); + Connection create(ArangoConfig config, HostDescription host, ConnectionPool pool); } diff --git a/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java b/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java index 91c12bb02..0db87c0c3 100644 --- a/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java @@ -20,18 +20,22 @@ package com.arangodb.internal.net; -import com.arangodb.config.HostDescription; +import com.arangodb.arch.UsedInApi; import java.io.Closeable; +import java.util.concurrent.CompletableFuture; /** * @author Mark Vollmary */ +@UsedInApi public interface ConnectionPool extends Closeable { - Connection createConnection(final HostDescription host); + Connection createConnection(); - Connection connection(); + CompletableFuture connection(); + + void release(final Connection connection); void setJwt(String jwt); diff --git a/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index 8337a67bf..9f22ee50a 100644 --- a/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -23,24 +23,28 @@ import com.arangodb.ArangoDBException; import com.arangodb.config.HostDescription; import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.util.AsyncQueue; import java.io.IOException; -import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; -/** - * @author Mark Vollmary - */ public class ConnectionPoolImpl implements ConnectionPool { + public static final int HTTP1_SLOTS = 1; // HTTP/1: max 1 pending request + public static final int HTTP1_SLOTS_PIPELINING = 10; // HTTP/1: max pipelining + public static final int HTTP2_SLOTS = 32; // HTTP/2: max streams, hard-coded see BTS-2049 + + private final AsyncQueue slots = new AsyncQueue<>(); private final HostDescription host; private final ArangoConfig config; private final int maxConnections; private final List connections; private final ConnectionFactory factory; - private int current; + private final int maxSlots; private volatile String jwt = null; - private boolean closed = false; + private volatile boolean closed = false; public ConnectionPoolImpl(final HostDescription host, final ArangoConfig config, final ConnectionFactory factory) { super(); @@ -48,39 +52,48 @@ public ConnectionPoolImpl(final HostDescription host, final ArangoConfig config, this.config = config; this.maxConnections = config.getMaxConnections(); this.factory = factory; - connections = new ArrayList<>(); - current = 0; + connections = new CopyOnWriteArrayList<>(); + switch (config.getProtocol()) { + case HTTP_JSON: + case HTTP_VPACK: + maxSlots = config.getPipelining() ? HTTP1_SLOTS_PIPELINING : HTTP1_SLOTS; + break; + default: + maxSlots = HTTP2_SLOTS; + } } @Override - public Connection createConnection(final HostDescription host) { - Connection c = factory.create(config, host); + public Connection createConnection() { + Connection c = factory.create(config, host, this); c.setJwt(jwt); return c; } @Override - public synchronized Connection connection() { + public CompletableFuture connection() { if (closed) { throw new ArangoDBException("Connection pool already closed!"); } - final Connection connection; - if (connections.size() < maxConnections) { - connection = createConnection(host); + Connection connection = createConnection(); connections.add(connection); - current++; - } else { - final int index = Math.floorMod(current++, connections.size()); - connection = connections.get(index); + for (int i = 0; i < maxSlots; i++) { + slots.offer((connection)); + } } - return connection; + return slots.poll(); + } + + @Override + public void release(Connection connection) { + slots.offer(connection); } @Override - public synchronized void setJwt(String jwt) { + public void setJwt(String jwt) { if (jwt != null) { this.jwt = jwt; for (Connection connection : connections) { @@ -90,18 +103,17 @@ public synchronized void setJwt(String jwt) { } @Override - public synchronized void close() throws IOException { + public void close() throws IOException { closed = true; for (final Connection connection : connections) { connection.close(); } - connections.clear(); } @Override public String toString() { return "ConnectionPoolImpl [host=" + host + ", maxConnections=" + maxConnections + ", connections=" - + connections.size() + ", current=" + current + ", factory=" + factory.getClass().getSimpleName() + "]"; + + connections.size() + ", factory=" + factory.getClass().getSimpleName() + "]"; } } diff --git a/core/src/main/java/com/arangodb/internal/net/Host.java b/core/src/main/java/com/arangodb/internal/net/Host.java index 07fd3c6ee..b2afdd8e1 100644 --- a/core/src/main/java/com/arangodb/internal/net/Host.java +++ b/core/src/main/java/com/arangodb/internal/net/Host.java @@ -24,6 +24,7 @@ import com.arangodb.config.HostDescription; import java.io.IOException; +import java.util.concurrent.CompletableFuture; /** * @author Mark Vollmary @@ -33,9 +34,7 @@ public interface Host { HostDescription getDescription(); - Connection connection(); - - void closeOnError(); + CompletableFuture connection(); void close() throws IOException; @@ -44,5 +43,4 @@ public interface Host { void setMarkforDeletion(boolean markforDeletion); void setJwt(String jwt); - } diff --git a/core/src/main/java/com/arangodb/internal/net/HostImpl.java b/core/src/main/java/com/arangodb/internal/net/HostImpl.java index 1ef822618..0277f8246 100644 --- a/core/src/main/java/com/arangodb/internal/net/HostImpl.java +++ b/core/src/main/java/com/arangodb/internal/net/HostImpl.java @@ -20,10 +20,10 @@ package com.arangodb.internal.net; -import com.arangodb.ArangoDBException; import com.arangodb.config.HostDescription; import java.io.IOException; +import java.util.concurrent.CompletableFuture; /** * @author Mark Vollmary @@ -51,19 +51,10 @@ public HostDescription getDescription() { } @Override - public Connection connection() { + public CompletableFuture connection() { return connectionPool.connection(); } - @Override - public void closeOnError() { - try { - connectionPool.close(); - } catch (final IOException e) { - throw ArangoDBException.of(e); - } - } - @Override public String toString() { return "HostImpl [connectionPool=" + connectionPool + ", description=" + description + ", markforDeletion=" diff --git a/core/src/main/java/com/arangodb/internal/util/AsyncQueue.java b/core/src/main/java/com/arangodb/internal/util/AsyncQueue.java new file mode 100644 index 000000000..d3b1a223a --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/util/AsyncQueue.java @@ -0,0 +1,45 @@ +package com.arangodb.internal.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.concurrent.*; + +public class AsyncQueue { + private static final Logger LOGGER = LoggerFactory.getLogger(AsyncQueue.class); + private final Queue> requests = new ConcurrentLinkedQueue<>(); + private final Queue offers = new ArrayDeque<>(); + + public synchronized CompletableFuture poll() { + LOGGER.trace("poll()"); + T o = offers.poll(); + if (o != null) { + LOGGER.trace("poll(): short-circuit: {}", o); + return CompletableFuture.completedFuture(o); + } + CompletableFuture r = new CompletableFuture<>(); + LOGGER.trace("poll(): enqueue request: {}", r); + requests.add(r); + return r; + } + + public void offer(T o) { + LOGGER.trace("offer({})", o); + CompletableFuture r = requests.poll(); + if (r == null) { + synchronized (this) { + r = requests.poll(); + if (r == null) { + LOGGER.trace("offer({}): enqueue", o); + offers.add(o); + } + } + } + if (r != null) { + LOGGER.trace("offer({}): short-circuit: {}", o, r); + r.complete(o); + } + } +} diff --git a/core/src/main/java/com/arangodb/model/AqlQueryOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryOptions.java index f51f419b2..6b223b82d 100644 --- a/core/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -236,6 +236,7 @@ public static final class Options implements Cloneable { private Long spillOverThresholdMemoryUsage; private Long spillOverThresholdNumRows; private Boolean stream; + private Boolean usePlanCache; @JsonInclude @JsonAnyGetter @@ -354,6 +355,10 @@ public Boolean getStream() { return stream; } + public Boolean getUsePlanCache() { + return usePlanCache; + } + public void setAllPlans(Boolean allPlans) { this.allPlans = allPlans; } @@ -446,6 +451,10 @@ public void setStream(Boolean stream) { this.stream = stream; } + public void setUsePlanCache(Boolean usePlanCache) { + this.usePlanCache = usePlanCache; + } + @Override public Options clone() { try { @@ -961,6 +970,11 @@ public Boolean getStream() { return getOptions().getStream(); } + @JsonIgnore + public Boolean getUsePlanCache() { + return getOptions().getUsePlanCache(); + } + /** * @param stream Specify true and the query will be executed in a streaming fashion. The query result is not * stored on @@ -983,6 +997,20 @@ public AqlQueryOptions stream(final Boolean stream) { return this; } + /** + * @param usePlanCache Set this option to true to utilize a cached query plan or add the execution plan of this + * query to the cache if it’s not in the cache yet. Otherwise, the plan cache is bypassed + * (introduced in v3.12.4). + * Query plan caching can reduce the total time for processing queries by avoiding to parse, + * plan, and optimize queries over and over again that effectively have the same execution plan + * with at most some changes to bind parameter values. + * @return this + */ + public AqlQueryOptions usePlanCache(final Boolean usePlanCache) { + getOptions().setUsePlanCache(usePlanCache); + return this; + } + @JsonIgnore public Collection getRules() { return getOptions().getOptimizer().getRules(); diff --git a/core/src/main/java/com/arangodb/model/ExplainAqlQueryOptions.java b/core/src/main/java/com/arangodb/model/ExplainAqlQueryOptions.java index 4d4d2f511..60d82f51e 100644 --- a/core/src/main/java/com/arangodb/model/ExplainAqlQueryOptions.java +++ b/core/src/main/java/com/arangodb/model/ExplainAqlQueryOptions.java @@ -554,6 +554,11 @@ public Boolean getStream() { return getOptions().getStream(); } + @JsonIgnore + public Boolean getUsePlanCache() { + return getOptions().getUsePlanCache(); + } + /** * @param stream Specify true and the query will be executed in a streaming fashion. The query result is not * stored on @@ -576,6 +581,20 @@ public ExplainAqlQueryOptions stream(final Boolean stream) { return this; } + /** + * @param usePlanCache Set this option to true to utilize a cached query plan or add the execution plan of this + * query to the cache if it’s not in the cache yet. Otherwise, the plan cache is bypassed + * (introduced in v3.12.4). + * Query plan caching can reduce the total time for processing queries by avoiding to parse, + * plan, and optimize queries over and over again that effectively have the same execution plan + * with at most some changes to bind parameter values. + * @return this + */ + public ExplainAqlQueryOptions usePlanCache(final Boolean usePlanCache) { + getOptions().setUsePlanCache(usePlanCache); + return this; + } + @JsonIgnore public Collection getRules() { return getOptions().getOptimizer().getRules(); diff --git a/docker/start_db.sh b/docker/start_db.sh index 4c0c2e9a2..e8c58ebcd 100755 --- a/docker/start_db.sh +++ b/docker/start_db.sh @@ -66,7 +66,7 @@ docker run -d \ --starter.address="${GW}" \ --docker.image="${DOCKER_IMAGE}" \ --starter.local --starter.mode=${STARTER_MODE} --all.log.level=debug --all.log.output=+ --log.verbose \ - --all.server.descriptors-minimum=1024 --all.javascript.allow-admin-execute=true + --all.server.descriptors-minimum=1024 --all.javascript.allow-admin-execute=true --all.server.maximal-threads=128 wait_server() { diff --git a/driver/pom.xml b/driver/pom.xml index 0f03f18e0..a8a3a7cd3 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 arangodb-java-driver diff --git a/http-protocol/pom.xml b/http-protocol/pom.xml index 83507cdec..514e99c34 100644 --- a/http-protocol/pom.xml +++ b/http-protocol/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 http-protocol diff --git a/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java b/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java index 87a47c760..d777f0e3f 100644 --- a/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java +++ b/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java @@ -29,6 +29,7 @@ import com.arangodb.internal.RequestType; import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; +import com.arangodb.internal.net.ConnectionPool; import com.arangodb.internal.serde.ContentTypeFactory; import com.arangodb.internal.util.EncodeUtils; import io.netty.handler.ssl.ApplicationProtocolConfig; @@ -63,6 +64,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import static com.arangodb.internal.net.ConnectionPoolImpl.HTTP1_SLOTS_PIPELINING; +import static com.arangodb.internal.net.ConnectionPoolImpl.HTTP2_SLOTS; + /** * @author Mark Vollmary @@ -81,14 +85,16 @@ public class HttpConnection implements Connection { private final WebClient client; private final Integer timeout; private final MultiMap commonHeaders = MultiMap.caseInsensitiveMultiMap(); + private final Vertx vertx; private final Vertx vertxToClose; + private final ConnectionPool pool; private static String getUserAgent() { return "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + System.getProperty("java.specification.version") + ")"; } - HttpConnection(final ArangoConfig config, final HostDescription host, final HttpProtocolConfig protocolConfig) { - super(); + HttpConnection(final ArangoConfig config, final HttpProtocolConfig protocolConfig, final HostDescription host, final ConnectionPool pool) { + this.pool = pool; Protocol protocol = config.getProtocol(); ContentType contentType = ContentTypeFactory.of(protocol); if (contentType == ContentType.VPACK) { @@ -112,20 +118,19 @@ private static String getUserAgent() { config.getUser(), Optional.ofNullable(config.getPassword()).orElse("") ).toHttpAuthorization(); - Vertx vertxToUse; if (protocolConfig.getVertx() != null) { // reuse existing Vert.x - vertxToUse = protocolConfig.getVertx(); + vertx = protocolConfig.getVertx(); // Vert.x will not be closed when connection is closed vertxToClose = null; LOGGER.debug("Reusing existing Vert.x instance"); } else { // create a new Vert.x instance LOGGER.debug("Creating new Vert.x instance"); - vertxToUse = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); - vertxToUse.runOnContext(e -> Thread.currentThread().setName("adb-http-" + THREAD_COUNT.getAndIncrement())); + vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); + vertx.runOnContext(e -> Thread.currentThread().setName("adb-http-" + THREAD_COUNT.getAndIncrement())); // Vert.x be closed when connection is closed - vertxToClose = vertxToUse; + vertxToClose = vertx; } int intTtl = Optional.ofNullable(config.getConnectionTtl()) @@ -148,7 +153,9 @@ private static String getUserAgent() { .setLogActivity(true) .setKeepAlive(true) .setTcpKeepAlive(true) - .setPipelining(true) + .setPipelining(config.getPipelining()) + .setPipeliningLimit(HTTP1_SLOTS_PIPELINING) + .setHttp2MultiplexingLimit(HTTP2_SLOTS) .setReuseAddress(true) .setReusePort(true) .setHttp2ClearTextUpgrade(false) @@ -205,7 +212,7 @@ public SslContextFactory sslContextFactory() { }); } - client = WebClient.create(vertxToUse, webClientOptions); + client = WebClient.create(vertx, webClientOptions); } private static String buildUrl(final InternalRequest request) { @@ -265,6 +272,11 @@ private HttpMethod requestTypeToHttpMethod(RequestType requestType) { } } + @Override + public void release() { + vertx.runOnContext(__ -> pool.release(this)); + } + @Override @UnstableApi public CompletableFuture executeAsync(@UnstableApi final InternalRequest request) { @@ -273,7 +285,7 @@ public CompletableFuture executeAsync(@UnstableApi final Inter return rfuture; } - public void doExecute(@UnstableApi final InternalRequest request, @UnstableApi final CompletableFuture rfuture) { + private void doExecute(@UnstableApi final InternalRequest request, @UnstableApi final CompletableFuture rfuture) { String path = buildUrl(request); HttpRequest httpRequest = client .request(requestTypeToHttpMethod(request.getRequestType()), path) diff --git a/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java b/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java index 69980aec3..72c8c9086 100644 --- a/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java +++ b/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java @@ -26,6 +26,7 @@ import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.ConnectionPool; import io.vertx.core.Vertx; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +50,9 @@ public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig cfg) { @Override @UnstableApi - public Connection create(@UnstableApi final ArangoConfig config, final HostDescription host) { - return new HttpConnection(config, host, protocolConfig); + public Connection create(@UnstableApi final ArangoConfig config, + final HostDescription host, + @UnstableApi final ConnectionPool pool) { + return new HttpConnection(config, protocolConfig, host, pool); } } diff --git a/jackson-serde-json/pom.xml b/jackson-serde-json/pom.xml index 2b636a780..948c175d4 100644 --- a/jackson-serde-json/pom.xml +++ b/jackson-serde-json/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 jackson-serde-json diff --git a/jackson-serde-vpack/pom.xml b/jackson-serde-vpack/pom.xml index 5dbee1c4c..b2d068133 100644 --- a/jackson-serde-vpack/pom.xml +++ b/jackson-serde-vpack/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 jackson-serde-vpack diff --git a/jsonb-serde/pom.xml b/jsonb-serde/pom.xml index 8738b2508..7027b9d02 100644 --- a/jsonb-serde/pom.xml +++ b/jsonb-serde/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 jsonb-serde diff --git a/pom.xml b/pom.xml index 9f1ee093f..a574ba455 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.arangodb arangodb-java-driver-parent - 7.17.0 + 7.20.0 2016 release-parent @@ -42,7 +42,7 @@ arangodb-1 target/spotbugsXml.xml site/jacoco/jacoco.xml - 23.1.1 + 24.2.1 @@ -83,6 +83,13 @@ + + com.fasterxml.jackson + jackson-bom + 2.19.0 + import + pom + io.vertx vertx-stack-depchain @@ -90,13 +97,6 @@ pom import - - com.fasterxml.jackson - jackson-bom - 2.18.2 - import - pom - com.google.code.findbugs jsr305 @@ -105,7 +105,7 @@ org.slf4j slf4j-api - 2.0.9 + 2.0.17 jakarta.json @@ -145,7 +145,7 @@ com.arangodb jackson-dataformat-velocypack - 4.5.0 + 4.6.0 com.arangodb @@ -178,7 +178,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.3.0 + 3.5.0 enforce @@ -199,7 +199,7 @@ - 3.6 + 3.6.3 @@ -209,14 +209,51 @@ org.codehaus.mojo extra-enforcer-rules - 1.8.0 + 1.10.0 + + org.codehaus.mojo + versions-maven-plugin + 2.18.0 + + + + + + + regex + (?i).*(alpha|beta|m|rc).*(\d+)? + + + + + io.vertx + + + regex + 5..* + + + + + io.netty + + + regex + .* + + + + + + + org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.4 10 @@ -224,7 +261,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 true ossrh @@ -241,7 +278,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.14.0 -Xlint:unchecked @@ -261,22 +298,22 @@ org.apache.maven.plugins maven-clean-plugin - 3.4.0 + 3.5.0 org.apache.maven.plugins maven-install-plugin - 3.1.2 + 3.1.4 org.apache.maven.plugins maven-site-plugin - 3.12.1 + 3.21.0 org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.5.3 true @@ -284,12 +321,12 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.1 org.jacoco jacoco-maven-plugin - 0.8.12 + 0.8.13 org.apache.maven.plugins @@ -299,12 +336,12 @@ org.sonarsource.scanner.maven sonar-maven-plugin - 4.0.0.4121 + 5.1.0.4751 org.apache.maven.plugins maven-shade-plugin - 3.4.1 + 3.6.0 com.google.code.maven-replacer-plugin @@ -314,7 +351,17 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.4.0 + 3.5.3 + + + org.codehaus.mojo + flatten-maven-plugin + 1.7.0 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 diff --git a/release-parent/pom.xml b/release-parent/pom.xml index 5cac2c6b5..6a65de066 100644 --- a/release-parent/pom.xml +++ b/release-parent/pom.xml @@ -6,7 +6,7 @@ com.arangodb arangodb-java-driver-parent - 7.17.0 + 7.20.0 pom @@ -24,7 +24,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 @@ -36,7 +36,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.8.0 @@ -57,7 +56,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.2.7 --pinentry-mode @@ -77,7 +76,6 @@ org.codehaus.mojo flatten-maven-plugin - 1.4.1 oss @@ -139,7 +137,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.3.4 + 4.9.3.0 spotbugs/spotbugs-exclude.xml diff --git a/shaded/pom.xml b/shaded/pom.xml index b3316a9c7..a7be647e1 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 arangodb-java-driver-shaded @@ -164,6 +164,12 @@ META-INF/** + + com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp + + META-INF/MANIFEST.MF + + diff --git a/shaded/src/main/java/graal/netty/graal/NettySubstitutions.java b/shaded/src/main/java/graal/netty/graal/NettySubstitutions.java index fb9b8b1bb..4eab2181b 100644 --- a/shaded/src/main/java/graal/netty/graal/NettySubstitutions.java +++ b/shaded/src/main/java/graal/netty/graal/NettySubstitutions.java @@ -166,7 +166,6 @@ final class Target_io_netty_handler_ssl_JdkSslClientContext { } } - @TargetClass(className = "io.netty.handler.ssl.SslHandler$SslEngineType") final class Target_io_netty_handler_ssl_SslHandler$SslEngineType { @@ -237,7 +236,6 @@ static SslContext newClientContextInternal(SslProvider provider, Provider sslCon } } - @TargetClass(className = "io.netty.handler.ssl.JdkDefaultApplicationProtocolNegotiator") final class Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator { diff --git a/test-functional/pom.xml b/test-functional/pom.xml index 288f9df55..d1b319e7d 100644 --- a/test-functional/pom.xml +++ b/test-functional/pom.xml @@ -8,7 +8,7 @@ ../test-parent com.arangodb test-parent - 7.17.0 + 7.20.0 test-functional @@ -151,7 +151,7 @@ org.graalvm.buildtools native-maven-plugin - 0.10.2 + 0.10.6 true @@ -175,6 +175,23 @@ + + no-native + + + native + !true + + + + + io.qameta.allure + allure-junit5 + 2.29.1 + test + + + static-code-analysis diff --git a/test-functional/src/test-default/java/graal/netty/graal/NettySubstitutions.java b/test-functional/src/test-default/java/graal/netty/graal/NettySubstitutions.java index fb9b8b1bb..4eab2181b 100644 --- a/test-functional/src/test-default/java/graal/netty/graal/NettySubstitutions.java +++ b/test-functional/src/test-default/java/graal/netty/graal/NettySubstitutions.java @@ -166,7 +166,6 @@ final class Target_io_netty_handler_ssl_JdkSslClientContext { } } - @TargetClass(className = "io.netty.handler.ssl.SslHandler$SslEngineType") final class Target_io_netty_handler_ssl_SslHandler$SslEngineType { @@ -237,7 +236,6 @@ static SslContext newClientContextInternal(SslProvider provider, Provider sslCon } } - @TargetClass(className = "io.netty.handler.ssl.JdkDefaultApplicationProtocolNegotiator") final class Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator { diff --git a/test-functional/src/test/java/com/arangodb/UserAgentTest.java b/test-functional/src/test/java/com/arangodb/UserAgentTest.java index 9bc0d8523..f8d1008ff 100644 --- a/test-functional/src/test/java/com/arangodb/UserAgentTest.java +++ b/test-functional/src/test/java/com/arangodb/UserAgentTest.java @@ -10,7 +10,7 @@ class UserAgentTest extends BaseJunit5 { - private static final String EXPECTED_VERSION = "7.17.0"; + private static final String EXPECTED_VERSION = "7.20.0"; private static final boolean SHADED = Boolean.parseBoolean(System.getProperty("shaded")); diff --git a/test-functional/src/test/java/com/arangodb/internal/HostHandlerTest.java b/test-functional/src/test/java/com/arangodb/internal/HostHandlerTest.java index 674c14851..109a9eb5e 100644 --- a/test-functional/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/test-functional/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.List; +import java.util.concurrent.CompletableFuture; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -39,15 +40,20 @@ class HostHandlerTest { private static final ConnectionPool mockCP = new ConnectionPool() { @Override - public Connection createConnection(HostDescription host) { + public Connection createConnection() { return null; } @Override - public Connection connection() { + public CompletableFuture connection() { return null; } + @Override + public void release(Connection connection) { + + } + @Override public void setJwt(String jwt) { diff --git a/test-functional/src/test/java/com/arangodb/model/AqlQueryOptionsTest.java b/test-functional/src/test/java/com/arangodb/model/AqlQueryOptionsTest.java index 39e9c1c43..c779464a1 100644 --- a/test-functional/src/test/java/com/arangodb/model/AqlQueryOptionsTest.java +++ b/test-functional/src/test/java/com/arangodb/model/AqlQueryOptionsTest.java @@ -15,11 +15,13 @@ void cloneable() { AqlQueryOptions options = new AqlQueryOptions() .cache(true) .stream(true) + .usePlanCache(true) .rules(rules) .shardIds("a", "b"); AqlQueryOptions clone = options.clone(); assertThat(clone.getCache()).isEqualTo(options.getCache()); assertThat(clone.getStream()).isEqualTo(options.getStream()); + assertThat(clone.getUsePlanCache()).isEqualTo(options.getUsePlanCache()); assertThat(clone.getRules()) .isEqualTo(options.getRules()) .isNotSameAs(options.getRules()); diff --git a/test-functional/src/test/resources/allure.properties b/test-functional/src/test/resources/allure.properties new file mode 100644 index 000000000..80b02dde9 --- /dev/null +++ b/test-functional/src/test/resources/allure.properties @@ -0,0 +1 @@ +allure.results.directory=target/allure-results diff --git a/test-functional/src/test/resources/simplelogger.properties b/test-functional/src/test/resources/simplelogger.properties index c375e20ef..a2a4ce6d5 100644 --- a/test-functional/src/test/resources/simplelogger.properties +++ b/test-functional/src/test/resources/simplelogger.properties @@ -10,3 +10,5 @@ org.slf4j.simpleLogger.defaultLogLevel=info #org.slf4j.simpleLogger.log.com.arangodb.internal.serde.JacksonUtils=debug #org.slf4j.simpleLogger.log.com.arangodb.internal.net.Communication=debug #org.slf4j.simpleLogger.log.com.arangodb.internal.serde.InternalSerdeImpl=debug +#org.slf4j.simpleLogger.log.io.netty.handler.logging.LoggingHandler=debug +#org.slf4j.simpleLogger.log.io.netty.handler.codec.http2.Http2FrameLogger=debug diff --git a/test-non-functional/pom.xml b/test-non-functional/pom.xml index 0ca7db923..cc802d7f8 100644 --- a/test-non-functional/pom.xml +++ b/test-non-functional/pom.xml @@ -8,7 +8,7 @@ ../test-parent com.arangodb test-parent - 7.17.0 + 7.20.0 test-non-functional @@ -59,7 +59,7 @@ io.smallrye.config smallrye-config-core - 2.13.3 + 3.13.1 test diff --git a/test-non-functional/src/test/java/concurrency/ConnectionLoadBalanceTest.java b/test-non-functional/src/test/java/concurrency/ConnectionLoadBalanceTest.java new file mode 100644 index 000000000..a3f5200a2 --- /dev/null +++ b/test-non-functional/src/test/java/concurrency/ConnectionLoadBalanceTest.java @@ -0,0 +1,113 @@ +package concurrency; + +import com.arangodb.*; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.internal.net.ConnectionPoolImpl; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.TestUtils; + +import java.time.Duration; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static org.awaitility.Awaitility.await; + +public class ConnectionLoadBalanceTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionLoadBalanceTest.class); + + public static Stream configs() { + return Stream.of( + // FIXME: DE-1017 + // new Config(Protocol.VST, 1), + // new Config(Protocol.VST, 2), + new Config(Protocol.HTTP_JSON, 10), + new Config(Protocol.HTTP_JSON, 20), + new Config(Protocol.HTTP2_JSON, 1), + new Config(Protocol.HTTP2_JSON, 2) + ).map(Arguments::of); + } + + // Test the requests load balancing across different connections, when all the slots except 1 are busy + @MethodSource("configs") + @ParameterizedTest + void loadBalanceToAvailableSlots(Config cfg) throws InterruptedException { + doTestLoadBalance(cfg, 1); + } + + // Test the requests load balancing across different connections, when all the slots are busy + @MethodSource("configs") + @ParameterizedTest + void loadBalanceAllBusy(Config cfg) throws InterruptedException { + doTestLoadBalance(cfg, 2); + } + + void doTestLoadBalance(Config cfg, int sleepCycles) throws InterruptedException { + int longTasksCount = cfg.maxStreams() * cfg.maxConnections * sleepCycles - 1; + int shortTasksCount = 10; + long sleepDuration = 2; + + ArangoDatabaseAsync db = new ArangoDB.Builder() + .loadProperties(ArangoConfigProperties.fromFile()) + .protocol(cfg.protocol) + .serde(TestUtils.createSerde(cfg.protocol)) + .maxConnections(cfg.maxConnections) + .build().async().db(); + + LOGGER.debug("starting..."); + + CompletableFuture longRunningTasks = CompletableFuture.allOf( + IntStream.range(0, longTasksCount) + .mapToObj(__ -> + db.query("RETURN SLEEP(@duration)", Void.class, Map.of("duration", sleepDuration))) + .toArray(CompletableFuture[]::new) + ); + + Thread.sleep(100); + + CompletableFuture shortRunningTasks = CompletableFuture.allOf( + IntStream.range(0, shortTasksCount) + .mapToObj(__ -> db.getVersion()) + .toArray(CompletableFuture[]::new) + ); + + LOGGER.debug("awaiting..."); + + await() + .timeout(Duration.ofSeconds(sleepDuration * sleepCycles - 1L)) + .until(shortRunningTasks::isDone); + + LOGGER.debug("completed shortRunningTasks"); + + // join exceptional completions + shortRunningTasks.join(); + + await() + .timeout(Duration.ofSeconds(sleepDuration * sleepCycles + 2L)) + .until(longRunningTasks::isDone); + + LOGGER.debug("completed longRunningTasks"); + + // join exceptional completions + longRunningTasks.join(); + + db.arango().shutdown(); + } + + private record Config( + Protocol protocol, + int maxConnections + ) { + int maxStreams() { + return switch (protocol) { + case HTTP_JSON, HTTP_VPACK -> ConnectionPoolImpl.HTTP1_SLOTS; + default -> ConnectionPoolImpl.HTTP2_SLOTS; + }; + } + } +} diff --git a/test-non-functional/src/test/java/concurrency/ConnectionPoolConcurrencyTest.java b/test-non-functional/src/test/java/concurrency/ConnectionPoolConcurrencyTest.java index 618f229f3..bf9641e0c 100644 --- a/test-non-functional/src/test/java/concurrency/ConnectionPoolConcurrencyTest.java +++ b/test-non-functional/src/test/java/concurrency/ConnectionPoolConcurrencyTest.java @@ -4,10 +4,7 @@ import com.arangodb.internal.InternalRequest; import com.arangodb.internal.InternalResponse; import com.arangodb.internal.config.ArangoConfig; -import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.ConnectionPool; -import com.arangodb.internal.net.ConnectionPoolImpl; +import com.arangodb.internal.net.*; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -23,7 +20,7 @@ public class ConnectionPoolConcurrencyTest { cfg.setMaxConnections(10_000); } - private final ConnectionFactory cf = (config, host) -> new Connection() { + private final ConnectionFactory cf = (config, host, pool) -> new Connection() { @Override public void setJwt(String jwt) { } @@ -33,6 +30,10 @@ public CompletableFuture executeAsync(InternalRequest request) throw new UnsupportedOperationException(); } + @Override + public void release() { + } + @Override public void close() { } @@ -45,7 +46,7 @@ void foo() throws InterruptedException, ExecutionException, IOException { List> futures = es.invokeAll(Collections.nCopies(8, (Callable) () -> { for (int i = 0; i < 10_000; i++) { - cp.createConnection(HostDescription.parse("127.0.0.1:8529")); + cp.createConnection(); cp.connection(); cp.setJwt("foo"); } diff --git a/test-non-functional/src/test/java/mp/ArangoConfigPropertiesMPImpl.java b/test-non-functional/src/test/java/mp/ArangoConfigPropertiesMPImpl.java index 1a0407a4c..4cac7a647 100644 --- a/test-non-functional/src/test/java/mp/ArangoConfigPropertiesMPImpl.java +++ b/test-non-functional/src/test/java/mp/ArangoConfigPropertiesMPImpl.java @@ -23,6 +23,7 @@ public final class ArangoConfigPropertiesMPImpl implements ArangoConfigPropertie private Optional useSsl; private Optional verifyHost; private Optional chunkSize; + private Optional pipelining; private Optional maxConnections; private Optional connectionTtl; private Optional keepAliveInterval; @@ -80,6 +81,11 @@ public Optional getChunkSize() { return chunkSize; } + @Override + public Optional getPipelining() { + return pipelining; + } + @Override public Optional getMaxConnections() { return maxConnections; @@ -140,12 +146,12 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ArangoConfigPropertiesMPImpl that = (ArangoConfigPropertiesMPImpl) o; - return Objects.equals(hosts, that.hosts) && Objects.equals(protocol, that.protocol) && Objects.equals(user, that.user) && Objects.equals(password, that.password) && Objects.equals(jwt, that.jwt) && Objects.equals(timeout, that.timeout) && Objects.equals(useSsl, that.useSsl) && Objects.equals(verifyHost, that.verifyHost) && Objects.equals(chunkSize, that.chunkSize) && Objects.equals(maxConnections, that.maxConnections) && Objects.equals(connectionTtl, that.connectionTtl) && Objects.equals(keepAliveInterval, that.keepAliveInterval) && Objects.equals(acquireHostList, that.acquireHostList) && Objects.equals(acquireHostListInterval, that.acquireHostListInterval) && Objects.equals(loadBalancingStrategy, that.loadBalancingStrategy) && Objects.equals(responseQueueTimeSamples, that.responseQueueTimeSamples) && Objects.equals(compression, that.compression) && Objects.equals(compressionThreshold, that.compressionThreshold) && Objects.equals(compressionLevel, that.compressionLevel) && Objects.equals(serdeProviderClass, that.serdeProviderClass); + return Objects.equals(hosts, that.hosts) && Objects.equals(protocol, that.protocol) && Objects.equals(user, that.user) && Objects.equals(password, that.password) && Objects.equals(jwt, that.jwt) && Objects.equals(timeout, that.timeout) && Objects.equals(useSsl, that.useSsl) && Objects.equals(verifyHost, that.verifyHost) && Objects.equals(chunkSize, that.chunkSize) && Objects.equals(pipelining, that.pipelining) && Objects.equals(maxConnections, that.maxConnections) && Objects.equals(connectionTtl, that.connectionTtl) && Objects.equals(keepAliveInterval, that.keepAliveInterval) && Objects.equals(acquireHostList, that.acquireHostList) && Objects.equals(acquireHostListInterval, that.acquireHostListInterval) && Objects.equals(loadBalancingStrategy, that.loadBalancingStrategy) && Objects.equals(responseQueueTimeSamples, that.responseQueueTimeSamples) && Objects.equals(compression, that.compression) && Objects.equals(compressionThreshold, that.compressionThreshold) && Objects.equals(compressionLevel, that.compressionLevel) && Objects.equals(serdeProviderClass, that.serdeProviderClass); } @Override public int hashCode() { - return Objects.hash(hosts, protocol, user, password, jwt, timeout, useSsl, verifyHost, chunkSize, maxConnections, connectionTtl, keepAliveInterval, acquireHostList, acquireHostListInterval, loadBalancingStrategy, responseQueueTimeSamples, compression, compressionThreshold, compressionLevel, serdeProviderClass); + return Objects.hash(hosts, protocol, user, password, jwt, timeout, useSsl, verifyHost, chunkSize, pipelining, maxConnections, connectionTtl, keepAliveInterval, acquireHostList, acquireHostListInterval, loadBalancingStrategy, responseQueueTimeSamples, compression, compressionThreshold, compressionLevel, serdeProviderClass); } @Override @@ -160,6 +166,7 @@ public String toString() { ", useSsl=" + useSsl + ", verifyHost=" + verifyHost + ", chunkSize=" + chunkSize + + ", pipelining=" + pipelining + ", maxConnections=" + maxConnections + ", connectionTtl=" + connectionTtl + ", keepAliveInterval=" + keepAliveInterval + diff --git a/test-non-functional/src/test/java/mp/ConfigMPDefaultsTest.java b/test-non-functional/src/test/java/mp/ConfigMPDefaultsTest.java index 3ff81bd04..5a8f861ef 100644 --- a/test-non-functional/src/test/java/mp/ConfigMPDefaultsTest.java +++ b/test-non-functional/src/test/java/mp/ConfigMPDefaultsTest.java @@ -25,6 +25,7 @@ private void checkResult(ArangoConfigProperties config) { assertThat(config.getUseSsl()).isEmpty(); assertThat(config.getVerifyHost()).isEmpty(); assertThat(config.getChunkSize()).isEmpty(); + assertThat(config.getPipelining()).isEmpty(); assertThat(config.getMaxConnections()).isNotPresent(); assertThat(config.getConnectionTtl()).isNotPresent(); assertThat(config.getKeepAliveInterval()).isNotPresent(); diff --git a/test-non-functional/src/test/java/mp/ConfigMPTest.java b/test-non-functional/src/test/java/mp/ConfigMPTest.java index 4a7aaa993..5d5f605e3 100644 --- a/test-non-functional/src/test/java/mp/ConfigMPTest.java +++ b/test-non-functional/src/test/java/mp/ConfigMPTest.java @@ -23,6 +23,7 @@ class ConfigMPTest { private final Boolean useSsl = true; private final Boolean verifyHost = false; private final Integer vstChunkSize = 1234; + private final Boolean pipelining = true; private final Integer maxConnections = 123; private final Long connectionTtl = 12345L; private final Integer keepAliveInterval = 123456; @@ -58,6 +59,7 @@ private void checkResult(ArangoConfigProperties config) { assertThat(config.getUseSsl()).hasValue(useSsl); assertThat(config.getVerifyHost()).hasValue(verifyHost); assertThat(config.getChunkSize()).hasValue(vstChunkSize); + assertThat(config.getPipelining()).hasValue(pipelining); assertThat(config.getMaxConnections()) .isPresent() .hasValue(maxConnections); diff --git a/test-non-functional/src/test/java/mp/ConfigUtilsMP.java b/test-non-functional/src/test/java/mp/ConfigUtilsMP.java index dabd62cde..07277115f 100644 --- a/test-non-functional/src/test/java/mp/ConfigUtilsMP.java +++ b/test-non-functional/src/test/java/mp/ConfigUtilsMP.java @@ -1,7 +1,7 @@ package mp; import com.arangodb.config.ArangoConfigProperties; -import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.PropertiesConfigSourceLoader; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigBuilder; @@ -17,7 +17,7 @@ public static ArangoConfigProperties loadConfigMP(final String location) { public static ArangoConfigProperties loadConfigMP(final String location, final String prefix) { SmallRyeConfig cfg = new SmallRyeConfigBuilder() - .withSources(new PropertiesConfigSourceProvider(location, ConfigUtilsMP.class.getClassLoader(), false)) + .withSources(PropertiesConfigSourceLoader.inClassPath(location, 0, ConfigUtilsMP.class.getClassLoader())) .withMapping(ArangoConfigPropertiesMPImpl.class, prefix) .build(); return cfg.getConfigMapping(ArangoConfigPropertiesMPImpl.class, prefix); diff --git a/test-non-functional/src/test/resources/arangodb-config-test.properties b/test-non-functional/src/test/resources/arangodb-config-test.properties index ef25aaf11..1d5e675af 100644 --- a/test-non-functional/src/test/resources/arangodb-config-test.properties +++ b/test-non-functional/src/test/resources/arangodb-config-test.properties @@ -7,6 +7,7 @@ adb.timeout=9876 adb.useSsl=true adb.verifyHost=false adb.chunkSize=1234 +adb.pipelining=true adb.maxConnections=123 adb.connectionTtl=12345 adb.keepAliveInterval=123456 diff --git a/test-non-functional/src/test/resources/simplelogger.properties b/test-non-functional/src/test/resources/simplelogger.properties index 7649bd6c7..495a73812 100644 --- a/test-non-functional/src/test/resources/simplelogger.properties +++ b/test-non-functional/src/test/resources/simplelogger.properties @@ -9,3 +9,6 @@ org.slf4j.simpleLogger.showShortLogName=false org.slf4j.simpleLogger.defaultLogLevel=info #org.slf4j.simpleLogger.log.com.arangodb.internal.serde.JacksonUtils=debug #org.slf4j.simpleLogger.log.com.arangodb.internal.net.Communication=debug +#org.slf4j.simpleLogger.log.io.netty.handler.logging.LoggingHandler=debug +#org.slf4j.simpleLogger.log.io.netty.handler.codec.http2.Http2FrameLogger=debug +#org.slf4j.simpleLogger.log.com.arangodb.internal.util.AsyncQueue=trace diff --git a/test-parent/pom.xml b/test-parent/pom.xml index 9365739de..c17fcb594 100644 --- a/test-parent/pom.xml +++ b/test-parent/pom.xml @@ -7,7 +7,7 @@ com.arangodb arangodb-java-driver-parent - 7.17.0 + 7.20.0 pom @@ -15,7 +15,7 @@ false - 2.18.0 + 2.19.0 true true 17 @@ -60,6 +60,11 @@ assertj-core test + + org.awaitility + awaitility + test + @@ -74,29 +79,35 @@ org.junit junit-bom - 5.10.2 + 5.12.2 pom import org.eclipse yasson - 3.0.3 + 3.0.4 org.slf4j slf4j-simple - 2.0.9 + 2.0.17 org.assertj assertj-core - 3.25.3 + 3.27.3 + + + org.awaitility + awaitility + 4.3.0 + test com.tngtech.archunit archunit-junit5 - 1.2.1 + 1.4.1 @@ -121,7 +132,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.3.1 + 3.5.3 true diff --git a/test-perf/pom.xml b/test-perf/pom.xml index bc1484d18..e834ea725 100644 --- a/test-perf/pom.xml +++ b/test-perf/pom.xml @@ -7,7 +7,7 @@ ../test-parent com.arangodb test-parent - 7.17.0 + 7.20.0 test-perf @@ -43,7 +43,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 package diff --git a/test-resilience/pom.xml b/test-resilience/pom.xml index cb3103a73..ae662bb32 100644 --- a/test-resilience/pom.xml +++ b/test-resilience/pom.xml @@ -6,7 +6,7 @@ ../test-parent com.arangodb test-parent - 7.17.0 + 7.20.0 4.0.0 @@ -29,12 +29,6 @@ 2.1.7 test - - org.awaitility - awaitility - 4.2.0 - test - ch.qos.logback logback-classic diff --git a/tutorial/gradle/build.gradle b/tutorial/gradle/build.gradle index 580784686..0047761d2 100644 --- a/tutorial/gradle/build.gradle +++ b/tutorial/gradle/build.gradle @@ -12,7 +12,7 @@ repositories { } dependencies { - implementation 'com.arangodb:arangodb-java-driver:7.17.0' + implementation 'com.arangodb:arangodb-java-driver:7.20.0' } ext { diff --git a/tutorial/maven/pom.xml b/tutorial/maven/pom.xml index a307b71cb..a40773634 100644 --- a/tutorial/maven/pom.xml +++ b/tutorial/maven/pom.xml @@ -19,7 +19,7 @@ com.arangodb arangodb-java-driver - 7.17.0 + 7.20.0 diff --git a/vst-protocol/pom.xml b/vst-protocol/pom.xml index 2e8a559b7..262352ba2 100644 --- a/vst-protocol/pom.xml +++ b/vst-protocol/pom.xml @@ -8,7 +8,7 @@ ../release-parent com.arangodb release-parent - 7.17.0 + 7.20.0 vst-protocol diff --git a/vst-protocol/src/main/java/com/arangodb/vst/VstConnectionFactoryAsync.java b/vst-protocol/src/main/java/com/arangodb/vst/VstConnectionFactoryAsync.java index f0faca44f..1db7852a0 100644 --- a/vst-protocol/src/main/java/com/arangodb/vst/VstConnectionFactoryAsync.java +++ b/vst-protocol/src/main/java/com/arangodb/vst/VstConnectionFactoryAsync.java @@ -25,6 +25,7 @@ import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.ConnectionPool; import com.arangodb.vst.internal.VstConnectionAsync; /** @@ -35,8 +36,8 @@ public class VstConnectionFactoryAsync implements ConnectionFactory { @Override @UnstableApi - public Connection create(@UnstableApi final ArangoConfig config, final HostDescription host) { - return new VstConnectionAsync(config, host); + public Connection create(@UnstableApi final ArangoConfig config, final HostDescription host, @UnstableApi final ConnectionPool pool) { + return new VstConnectionAsync(config, host, pool); } } diff --git a/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnection.java b/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnection.java index ddd886d10..8b4cdc211 100644 --- a/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnection.java +++ b/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnection.java @@ -25,6 +25,7 @@ import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; +import com.arangodb.internal.net.ConnectionPool; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.ValueType; @@ -68,6 +69,7 @@ public abstract class VstConnection implements Connection { private final HostDescription host; private final Map sendTimestamps = new ConcurrentHashMap<>(); private final String connectionName; + private final ConnectionPool pool; private final byte[] keepAliveRequest = new VPackBuilder() .add(ValueType.ARRAY) .add(1) @@ -89,7 +91,7 @@ public abstract class VstConnection implements Connection { private OutputStream outputStream; private InputStream inputStream; - protected VstConnection(final ArangoConfig config, final HostDescription host) { + protected VstConnection(final ArangoConfig config, final HostDescription host, final ConnectionPool pool) { super(); timeout = config.getTimeout(); ttl = config.getConnectionTtl(); @@ -97,6 +99,7 @@ protected VstConnection(final ArangoConfig config, final HostDescription host) { useSsl = config.getUseSsl(); sslContext = config.getSslContext(); this.host = host; + this.pool = pool; connectionName = "connection_" + System.currentTimeMillis() + "_" + Math.random(); LOGGER.debug("[" + connectionName + "]: Connection created"); @@ -244,6 +247,11 @@ public synchronized void close() { } } + @Override + public void release() { + pool.release(this); + } + private synchronized void sendProtocolHeader() throws IOException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("[%s]: Send velocystream protocol header to %s", connectionName, socket)); diff --git a/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnectionAsync.java b/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnectionAsync.java index 8b74cbd57..5b128340e 100644 --- a/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnectionAsync.java +++ b/vst-protocol/src/main/java/com/arangodb/vst/internal/VstConnectionAsync.java @@ -25,6 +25,7 @@ import com.arangodb.internal.InternalRequest; import com.arangodb.internal.InternalResponse; import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.ConnectionPool; import com.arangodb.internal.serde.InternalSerde; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; @@ -51,8 +52,8 @@ public class VstConnectionAsync extends VstConnection private final InternalSerde serde; - public VstConnectionAsync(final ArangoConfig config, final HostDescription host) { - super(config, host); + public VstConnectionAsync(final ArangoConfig config, final HostDescription host, final ConnectionPool pool) { + super(config, host, pool); chunkSize = config.getChunkSize(); serde = config.getInternalSerde(); } @@ -98,7 +99,7 @@ public CompletableFuture executeAsync(final InternalRequest re return; } rfuture.complete(response); - } else { + } else { Throwable e = ex instanceof CompletionException ? ex.getCause() : ex; rfuture.completeExceptionally(e); }