addressTranslation, Credentials credentials, DriverOptions driverOptions) throws TypeDBDriverException {
+ return new DriverImpl(addressTranslation, credentials, driverOptions);
+ }
}
diff --git a/java/TypeDBExample.java b/java/TypeDBExample.java
index e127e429c7..cac14bb6ec 100644
--- a/java/TypeDBExample.java
+++ b/java/TypeDBExample.java
@@ -31,7 +31,7 @@
public class TypeDBExample {
public void example() {
// Open a driver connection. Try-with-resources can be used for automatic driver connection management
- try (Driver driver = TypeDB.driver(TypeDB.DEFAULT_ADDRESS, new Credentials("admin", "password"), new DriverOptions(false, null))) {
+ try (Driver driver = TypeDB.driver(TypeDB.DEFAULT_ADDRESS, new Credentials("admin", "password"), new DriverOptions().tlsEnabled(false))) {
// Create a database
driver.databases().create("typedb");
Database database = driver.databases().get("typedb");
diff --git a/java/api/ConsistencyLevel.java b/java/api/ConsistencyLevel.java
new file mode 100644
index 0000000000..711ed4c3ea
--- /dev/null
+++ b/java/api/ConsistencyLevel.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.typedb.driver.api;
+
+import com.typedb.driver.common.exception.TypeDBDriverException;
+
+import static com.typedb.driver.common.exception.ErrorMessage.Internal.UNEXPECTED_NATIVE_VALUE;
+import static com.typedb.driver.jni.typedb_driver.consistency_level_eventual;
+import static com.typedb.driver.jni.typedb_driver.consistency_level_replica_dependent;
+import static com.typedb.driver.jni.typedb_driver.consistency_level_strong;
+
+/**
+ * Consistency levels of operations against a distributed server. All driver methods have default
+ * recommended values, however, readonly operations can be configured in order to potentially
+ * speed up the execution (introducing risks of stale data) or test a specific replica.
+ * This setting does not affect clusters with a single node.
+ */
+public abstract class ConsistencyLevel {
+ public abstract com.typedb.driver.jni.ConsistencyLevel nativeValue();
+
+ public static ConsistencyLevel of(com.typedb.driver.jni.ConsistencyLevel nativeValue) {
+ if (nativeValue.getTag() == com.typedb.driver.jni.ConsistencyLevelTag.Strong) return new Strong();
+ else if (nativeValue.getTag() == com.typedb.driver.jni.ConsistencyLevelTag.Eventual) return new Eventual();
+ else if (nativeValue.getTag() == com.typedb.driver.jni.ConsistencyLevelTag.ReplicaDependent) {
+ return new ReplicaDependent(nativeValue.getAddress());
+ }
+ throw new TypeDBDriverException(UNEXPECTED_NATIVE_VALUE);
+ }
+
+ public static com.typedb.driver.jni.ConsistencyLevel nativeValue(ConsistencyLevel consistencyLevel) {
+ if (consistencyLevel == null) {
+ return null;
+ } else {
+ return consistencyLevel.nativeValue();
+ }
+ }
+
+ /**
+ * Strongest consistency, always up-to-date due to the guarantee of the primary replica usage.
+ * May require more time for operation execution.
+ */
+ public static final class Strong extends ConsistencyLevel {
+ Strong() {
+ }
+
+ @Override
+ public com.typedb.driver.jni.ConsistencyLevel nativeValue() {
+ return newNative();
+ }
+
+ private static com.typedb.driver.jni.ConsistencyLevel newNative() {
+ return consistency_level_strong();
+ }
+
+ @Override
+ public String toString() {
+ return "Strong";
+ }
+ }
+
+ /**
+ * Allow stale reads from any replica. May not reflect latest writes. The execution may be
+ * eventually faster compared to other consistency levels.
+ */
+ public static final class Eventual extends ConsistencyLevel {
+ Eventual() {
+ }
+
+ @Override
+ public com.typedb.driver.jni.ConsistencyLevel nativeValue() {
+ return newNative();
+ }
+
+ private static com.typedb.driver.jni.ConsistencyLevel newNative() {
+ return consistency_level_eventual();
+ }
+
+ @Override
+ public String toString() {
+ return "Eventual";
+ }
+ }
+
+ /**
+ * The operation is executed against the provided replica address only. Its guarantees depend
+ * on the replica selected.
+ */
+ public static final class ReplicaDependent extends ConsistencyLevel {
+ private final String address;
+
+ public ReplicaDependent(String address) {
+ this.address = address;
+ }
+
+ @Override
+ public com.typedb.driver.jni.ConsistencyLevel nativeValue() {
+ return newNative(this.address);
+ }
+
+ private static com.typedb.driver.jni.ConsistencyLevel newNative(String address) {
+ return consistency_level_replica_dependent(address);
+ }
+
+ /**
+ * Retrieves the address of the replica this consistency level depends on.
+ */
+ public String getAddress() {
+ return address;
+ }
+
+ @Override
+ public String toString() {
+ return "ReplicaDependent(" + address + ")";
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/api/Driver.java b/java/api/Driver.java
index acf156ff68..7f836a1bff 100644
--- a/java/api/Driver.java
+++ b/java/api/Driver.java
@@ -20,10 +20,15 @@
package com.typedb.driver.api;
import com.typedb.driver.api.database.DatabaseManager;
+import com.typedb.driver.api.server.ServerReplica;
+import com.typedb.driver.api.server.ServerVersion;
import com.typedb.driver.api.user.UserManager;
import com.typedb.driver.common.exception.TypeDBDriverException;
import javax.annotation.CheckReturnValue;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
public interface Driver extends AutoCloseable {
String LANGUAGE = "java";
@@ -39,12 +44,55 @@ public interface Driver extends AutoCloseable {
@CheckReturnValue
boolean isOpen();
+ /**
+ * Retrieves the server's version, using default strong consistency.
+ * See {@link #serverVersion(ConsistencyLevel)} for more details and options.
+ *
+ * Examples
+ *
+ * driver.serverVersion();
+ *
+ */
+ @CheckReturnValue
+ default ServerVersion serverVersion() {
+ return serverVersion(null);
+ }
+
+ /**
+ * Retrieves the server's version.
+ *
+ * Examples
+ *
+ * driver.serverVersion();
+ *
+ *
+ * @param consistencyLevel The consistency level to use for the operation
+ */
+ @CheckReturnValue
+ ServerVersion serverVersion(ConsistencyLevel consistencyLevel);
+
/**
* The DatabaseManager for this connection, providing access to database management methods.
+ *
+ * Examples
+ *
+ * driver.databases();
+ *
*/
@CheckReturnValue
DatabaseManager databases();
+ /**
+ * The UserManager for this connection, providing access to user management methods.
+ *
+ * Examples
+ *
+ * driver.users();
+ *
+ */
+ @CheckReturnValue
+ UserManager users();
+
/**
* Opens a communication tunnel (transaction) to the given database on the running TypeDB server.
*
@@ -75,23 +123,77 @@ public interface Driver extends AutoCloseable {
Transaction transaction(String database, Transaction.Type type, TransactionOptions options);
/**
- * Closes the driver. Before instantiating a new driver, the driver that’s currently open should first be closed.
+ * Set of Replica instances for this driver connection.
*
* Examples
*
- * driver.close()
+ * driver.replicas();
*
*/
- void close();
+ @CheckReturnValue
+ Set extends ServerReplica> replicas();
/**
- * The UserManager instance for this connection, providing access to user management methods.
+ * Returns the primary replica for this driver connection.
*
* Examples
*
- * driver.users();
+ * driver.primaryReplica();
*
*/
@CheckReturnValue
- UserManager users();
+ Optional extends ServerReplica> primaryReplica();
+
+ /**
+ * Registers a new replica in the cluster the driver is currently connected to. The registered
+ * replica will become available eventually, depending on the behavior of the whole cluster.
+ * To register a replica, its clustering address should be passed, not the connection address.
+ *
+ * Examples
+ *
+ * driver.registerReplica(2, "127.0.0.1:11729");
+ *
+ *
+ * @param replicaID The numeric identifier of the new replica
+ * @param address The address(es) of the TypeDB replica as a string
+ */
+ void registerReplica(long replicaID, String address);
+
+ /**
+ * Deregisters a replica from the cluster the driver is currently connected to. This replica
+ * will no longer play a raft role in this cluster.
+ *
+ * Examples
+ *
+ * driver.deregisterReplica(2);
+ *
+ *
+ * @param replicaID The numeric identifier of the deregistered replica
+ */
+ void deregisterReplica(long replicaID);
+
+ /**
+ * Updates address translation of the driver. This lets you actualize new translation
+ * information without recreating the driver from scratch. Useful after registering new
+ * replicas requiring address translation.
+ * This operation will update existing connections using the provided addresses.
+ *
+ * Examples
+ *
+ * driver.updateAddressTranslation(2);
+ *
+ *
+ * @param addressTranslation The translation of public TypeDB cluster replica addresses (keys) to server-side private addresses (values)
+ */
+ void updateAddressTranslation(Map addressTranslation);
+
+ /**
+ * Closes the driver. Before instantiating a new driver, the driver that’s currently open should first be closed.
+ *
+ * Examples
+ *
+ * driver.close();
+ *
+ */
+ void close();
}
diff --git a/java/api/DriverOptions.java b/java/api/DriverOptions.java
index f14e42ff9c..dbd2acb2e4 100644
--- a/java/api/DriverOptions.java
+++ b/java/api/DriverOptions.java
@@ -20,34 +20,211 @@
package com.typedb.driver.api;
import com.typedb.driver.common.NativeObject;
-import com.typedb.driver.common.exception.TypeDBDriverException;
+import com.typedb.driver.common.Validator;
-import javax.annotation.Nullable;
+import javax.annotation.CheckReturnValue;
+import java.util.Optional;
+import static com.typedb.driver.jni.typedb_driver.driver_options_get_tls_enabled;
+import static com.typedb.driver.jni.typedb_driver.driver_options_get_primary_failover_retries;
+import static com.typedb.driver.jni.typedb_driver.driver_options_get_replica_discovery_attempts;
+import static com.typedb.driver.jni.typedb_driver.driver_options_get_tls_root_ca_path;
+import static com.typedb.driver.jni.typedb_driver.driver_options_get_use_replication;
+import static com.typedb.driver.jni.typedb_driver.driver_options_has_replica_discovery_attempts;
+import static com.typedb.driver.jni.typedb_driver.driver_options_has_tls_root_ca_path;
import static com.typedb.driver.jni.typedb_driver.driver_options_new;
+import static com.typedb.driver.jni.typedb_driver.driver_options_set_tls_enabled;
+import static com.typedb.driver.jni.typedb_driver.driver_options_set_primary_failover_retries;
+import static com.typedb.driver.jni.typedb_driver.driver_options_set_replica_discovery_attempts;
+import static com.typedb.driver.jni.typedb_driver.driver_options_set_tls_root_ca_path;
+import static com.typedb.driver.jni.typedb_driver.driver_options_set_use_replication;
/**
- * User connection settings (TLS encryption, etc.) for connecting to TypeDB Server.
- *
- * Examples
- *
- * DriverOptions driverOptions = new DriverOptions(true, Path.of("path/to/ca-certificate.pem"));
- *
+ * TypeDB driver options. DriverOptions are used to specify the driver's connection behavior.
*/
public class DriverOptions extends NativeObject {
/**
- * @param isTlsEnabled Specify whether the connection to TypeDB Server must be done over TLS.
- * @param tlsRootCAPath Path to the CA certificate to use for authenticating server certificates.
+ * Produces a new DriverOptions object.
+ *
+ * Examples
+ *
+ * DriverOptions options = DriverOptions();
+ *
+ */
+ public DriverOptions() {
+ super(driver_options_new());
+ }
+
+ /**
+ * Returns the value set for the TLS flag in this DriverOptions object.
+ * Specifies whether the connection to TypeDB must be done over TLS.
+ *
+ * Examples
+ *
+ * options.tlsEnabled();
+ *
+ */
+ @CheckReturnValue
+ public Boolean tlsEnabled() {
+ return driver_options_get_tls_enabled(nativeObject);
+ }
+
+ /**
+ * Explicitly sets whether the connection to TypeDB must be done over TLS.
+ * WARNING: Setting this to false will make the driver sending passwords as plaintext. Defaults to true.
+ *
+ * Examples
+ *
+ * options.tlsEnabled(true);
+ *
+ *
+ * @param tlsEnabled Whether the connection to TypeDB must be done over TLS.
+ */
+ public DriverOptions tlsEnabled(boolean tlsEnabled) {
+ driver_options_set_tls_enabled(nativeObject, tlsEnabled);
+ return this;
+ }
+
+ /**
+ * Returns the TLS root CA set in this DriverOptions object.
+ * Specifies the root CA used in the TLS config for server certificates authentication.
+ * Uses system roots if None is set.
+ *
+ * Examples
+ *
+ * options.tlsRootCAPath();
+ *
+ */
+ @CheckReturnValue
+ public Optional tlsRootCAPath() {
+ if (driver_options_has_tls_root_ca_path(nativeObject))
+ return Optional.of(driver_options_get_tls_root_ca_path(nativeObject));
+ return Optional.empty();
+ }
+
+ /**
+ * Returns the TLS root CA set in this DriverOptions object.
+ * Specifies the root CA used in the TLS config for server certificates authentication.
+ * Uses system roots if None is set.
+ *
+ * Examples
+ *
+ * options.tlsRootCAPath(Optional.of("/path/to/ca-certificate.pem"));
+ *
+ *
+ * @param tlsRootCAPath The path to the TLS root CA. If None, system roots are used.
*/
- public DriverOptions(boolean isTlsEnabled, String tlsRootCAPath) { // TODO: Maybe Optional? Optional.of(Path.of(..))?..
- super(newNative(isTlsEnabled, tlsRootCAPath));
+ public DriverOptions tlsRootCAPath(Optional tlsRootCAPath) {
+ driver_options_set_tls_root_ca_path(nativeObject, tlsRootCAPath.orElse(null));
+ return this;
}
- private static com.typedb.driver.jni.DriverOptions newNative(boolean isTlsEnabled, @Nullable String tlsRootCAPath) {
- try {
- return driver_options_new(isTlsEnabled, tlsRootCAPath);
- } catch (com.typedb.driver.jni.Error error) {
- throw new TypeDBDriverException(error);
- }
+ /**
+ * Returns the value set for the replication usage flag in this DriverOptions object.
+ * Specifies whether the connection to TypeDB can use cluster replicas provided by the server
+ * or it should be limited to a single configured address.
+ *
+ * Examples
+ *
+ * options.useReplication();
+ *
+ */
+ @CheckReturnValue
+ public Boolean useReplication() {
+ return driver_options_get_use_replication(nativeObject);
+ }
+
+ /**
+ * Explicitly sets whether the connection to TypeDB can use cluster replicas provided by the server
+ * or it should be limited to a single configured address. Defaults to true.
+ *
+ * Examples
+ *
+ * options.useReplication(true);
+ *
+ *
+ * @param useReplication Whether the connection to TypeDB can use replication.
+ */
+ public DriverOptions useReplication(boolean useReplication) {
+ driver_options_set_use_replication(nativeObject, useReplication);
+ return this;
+ }
+
+ /**
+ * Returns the value set for the primary failover retries limit in this DriverOptions object.
+ * Limits the number of attempts to redirect a strongly consistent request to another
+ * primary replica in case of a failure due to the change of replica roles.
+ *
+ * Examples
+ *
+ * options.primaryFailoverRetries();
+ *
+ */
+ @CheckReturnValue
+ public Integer primaryFailoverRetries() {
+ return (int) driver_options_get_primary_failover_retries(nativeObject);
+ }
+
+ /**
+ * Explicitly sets the limit on the number of attempts to redirect a strongly consistent request to another
+ * primary replica in case of a failure due to the change of replica roles. Defaults to 1.
+ *
+ * Examples
+ *
+ * options.primaryFailoverRetries(1);
+ *
+ *
+ * @param primaryFailoverRetries The limit of primary failover retries.
+ */
+ public DriverOptions primaryFailoverRetries(int primaryFailoverRetries) {
+ Validator.requireNonNegative(primaryFailoverRetries, "primaryFailoverRetries");
+ driver_options_set_primary_failover_retries(nativeObject, primaryFailoverRetries);
+ return this;
+ }
+
+ /**
+ * Returns the value set for the replica discovery attempts limit in this DriverOptions object.
+ * Limits the number of driver attempts to discover a single working replica to perform an
+ * operation in case of a replica unavailability. Every replica is tested once, which means
+ * that at most:
+ * - {limit} operations are performed if the limit <= the number of replicas.
+ * - {number of replicas} operations are performed if the limit > the number of replicas.
+ * - {number of replicas} operations are performed if the limit is None.
+ * Affects every eventually consistent operation, including redirect failover, when the new
+ * primary replica is unknown.
+ *
+ * Examples
+ *
+ * options.replicaDiscoveryAttempts();
+ *
+ */
+ @CheckReturnValue
+ public Optional replicaDiscoveryAttempts() {
+ if (driver_options_has_replica_discovery_attempts(nativeObject))
+ return Optional.of((int) driver_options_get_replica_discovery_attempts(nativeObject));
+ return Optional.empty();
+ }
+
+ /**
+ * Limits the number of driver attempts to discover a single working replica to perform an
+ * operation in case of a replica unavailability. Every replica is tested once, which means
+ * that at most:
+ * - {limit} operations are performed if the limit <= the number of replicas.
+ * - {number of replicas} operations are performed if the limit > the number of replicas.
+ * - {number of replicas} operations are performed if the limit is None.
+ * Affects every eventually consistent operation, including redirect failover, when the new
+ * primary replica is unknown. If not set, the maximum (practically unlimited) value is used.
+ *
+ * Examples
+ *
+ * options.primaryFailoverRetries(1);
+ *
+ *
+ * @param replicaDiscoveryAttempts The limit of replica discovery attempts.
+ */
+ public DriverOptions replicaDiscoveryAttempts(int replicaDiscoveryAttempts) {
+ Validator.requireNonNegative(replicaDiscoveryAttempts, "replicaDiscoveryAttempts");
+ driver_options_set_replica_discovery_attempts(nativeObject, replicaDiscoveryAttempts);
+ return this;
}
}
diff --git a/java/api/QueryOptions.java b/java/api/QueryOptions.java
index 65e7b63967..c9c4138320 100644
--- a/java/api/QueryOptions.java
+++ b/java/api/QueryOptions.java
@@ -72,7 +72,7 @@ public Optional includeInstanceTypes() {
}
/**
- * Explicitly set the "include instance types" flag.
+ * Explicitly setsthe "include instance types" flag.
* If set, specifies if types should be included in instance structs returned in ConceptRow answers.
* This option allows reducing the amount of unnecessary data transmitted.
*
@@ -107,7 +107,7 @@ public Optional prefetchSize() {
}
/**
- * Explicitly set the prefetch size.
+ * Explicitly setsthe prefetch size.
* If set, specifies the number of extra query responses sent before the client side has to re-request more responses.
* Increasing this may increase performance for queries with a huge number of answers, as it can
* reduce the number of network round-trips at the cost of more resources on the server side.
diff --git a/java/api/TransactionOptions.java b/java/api/TransactionOptions.java
index cbf246b347..4b6d3d587d 100644
--- a/java/api/TransactionOptions.java
+++ b/java/api/TransactionOptions.java
@@ -25,15 +25,17 @@
import javax.annotation.CheckReturnValue;
import java.util.Optional;
+import static com.typedb.driver.jni.typedb_driver.transaction_options_get_read_consistency_level;
import static com.typedb.driver.jni.typedb_driver.transaction_options_get_schema_lock_acquire_timeout_millis;
import static com.typedb.driver.jni.typedb_driver.transaction_options_get_transaction_timeout_millis;
+import static com.typedb.driver.jni.typedb_driver.transaction_options_has_read_consistency_level;
import static com.typedb.driver.jni.typedb_driver.transaction_options_has_schema_lock_acquire_timeout_millis;
import static com.typedb.driver.jni.typedb_driver.transaction_options_has_transaction_timeout_millis;
import static com.typedb.driver.jni.typedb_driver.transaction_options_new;
+import static com.typedb.driver.jni.typedb_driver.transaction_options_set_read_consistency_level;
import static com.typedb.driver.jni.typedb_driver.transaction_options_set_schema_lock_acquire_timeout_millis;
import static com.typedb.driver.jni.typedb_driver.transaction_options_set_transaction_timeout_millis;
-
/**
* TypeDB transaction options. TransactionOptions object can be used to override
* the default server behaviour for opened transactions.
@@ -68,7 +70,7 @@ public Optional transactionTimeoutMillis() {
}
/**
- * Explicitly set a transaction timeout.
+ * Explicitly sets a transaction timeout.
* If set, specifies how long the driver should wait if opening a transaction is blocked by an exclusive schema write lock.
*
* Examples
@@ -116,4 +118,37 @@ public TransactionOptions schemaLockAcquireTimeoutMillis(int schemaLockAcquireTi
transaction_options_set_schema_lock_acquire_timeout_millis(nativeObject, schemaLockAcquireTimeoutMillis);
return this;
}
+
+ /**
+ * Returns the value set for the read consistency level in this TransactionOptions object.
+ * If set, specifies the requested consistency level of the transaction opening operation.
+ * Affects only read transactions, as write and schema transactions require primary replicas.
+ *
+ * Examples
+ *
+ * options.readConsistencyLevel();
+ *
+ */
+ public Optional readConsistencyLevel() {
+ if (transaction_options_has_read_consistency_level(nativeObject))
+ return Optional.of(ConsistencyLevel.of(transaction_options_get_read_consistency_level(nativeObject)));
+ return Optional.empty();
+ }
+
+ /**
+ * Explicitly sets read consistency level.
+ * If set, specifies the requested consistency level of the transaction opening operation.
+ * Affects only read transactions, as write and schema transactions require primary replicas.
+ *
+ * Examples
+ *
+ * options.schemaLockAcquireTimeoutMillis(schemaLockAcquireTimeoutMillis);
+ *
+ *
+ * @param readConsistencyLevel The requested consistency level
+ */
+ public TransactionOptions readConsistencyLevel(ConsistencyLevel readConsistencyLevel) {
+ transaction_options_set_read_consistency_level(nativeObject, readConsistencyLevel.nativeValue());
+ return this;
+ }
}
diff --git a/java/api/answer/ConceptRow.java b/java/api/answer/ConceptRow.java
index a137937a40..e2f84fcf01 100644
--- a/java/api/answer/ConceptRow.java
+++ b/java/api/answer/ConceptRow.java
@@ -78,7 +78,7 @@ public interface ConceptRow {
* conceptRow.get(columnName);
*
*
- * @param columnName the variable (column name from ``column_names``)
+ * @param columnName the variable (column name from column_names)
*/
@CheckReturnValue
Optional get(String columnName) throws TypeDBDriverException;
diff --git a/java/api/database/Database.java b/java/api/database/Database.java
index 4b2bb4bc15..66e69dc209 100644
--- a/java/api/database/Database.java
+++ b/java/api/database/Database.java
@@ -19,6 +19,7 @@
package com.typedb.driver.api.database;
+import com.typedb.driver.api.ConsistencyLevel;
import com.typedb.driver.common.exception.TypeDBDriverException;
import javax.annotation.CheckReturnValue;
@@ -27,12 +28,18 @@ public interface Database {
/**
* The database name as a string.
+ *
+ *