Skip to content

Commit

Permalink
Add 2 access options to Config and refactor DriverFactory (#1356)
Browse files Browse the repository at this point in the history
This update adds 2 getters for existing configuration options in `Config`:
- `routingTablePurgeDelayMillis()` - provides access to value configured via `ConfigBuilder.withRoutingTablePurgeDelay(long, TimeUnit)`
- `maxTransactionRetryTimeMillis()` - provides access to value configured via `ConfigBuilder.withMaxTransactionRetryTime(long, TimeUnit)`

It also includes internal `DriverFactory` refactoring.
  • Loading branch information
injectives authored Dec 20, 2022
1 parent b2fe6c2 commit a0f5b07
Show file tree
Hide file tree
Showing 25 changed files with 462 additions and 482 deletions.
83 changes: 48 additions & 35 deletions driver/src/main/java/org/neo4j/driver/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import org.neo4j.driver.internal.async.pool.PoolSettings;
import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.handlers.pulln.FetchSizeUtil;
import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
import org.neo4j.driver.net.ServerAddressResolver;
import org.neo4j.driver.util.Experimental;
import org.neo4j.driver.util.Immutable;
Expand Down Expand Up @@ -75,7 +75,9 @@ public final class Config implements Serializable {

private static final Config EMPTY = builder().build();

/** User defined logging */
/**
* User defined logging
*/
private final Logging logging;

private final boolean logLeakedSessions;
Expand All @@ -90,9 +92,9 @@ public final class Config implements Serializable {

private final long fetchSize;
private final long routingTablePurgeDelayMillis;
private final long maxTransactionRetryTimeMillis;

private final int connectionTimeoutMillis;
private final RetrySettings retrySettings;
private final ServerAddressResolver resolver;

private final int eventLoopThreads;
Expand All @@ -113,7 +115,7 @@ private Config(ConfigBuilder builder) {

this.connectionTimeoutMillis = builder.connectionTimeoutMillis;
this.routingTablePurgeDelayMillis = builder.routingTablePurgeDelayMillis;
this.retrySettings = builder.retrySettings;
this.maxTransactionRetryTimeMillis = builder.maxTransactionRetryTimeMillis;
this.resolver = builder.resolver;
this.fetchSize = builder.fetchSize;

Expand All @@ -123,6 +125,7 @@ private Config(ConfigBuilder builder) {

/**
* Logging provider
*
* @return the Logging provider to use
*/
public Logging logging() {
Expand Down Expand Up @@ -212,18 +215,21 @@ public static Config defaultConfig() {
}

/**
* @return the security setting to use when creating connections.
* Returns stale routing table purge delay.
*
* @return routing table purge delay
*/
SecuritySettings securitySettings() {
return securitySettings;
public long routingTablePurgeDelayMillis() {
return routingTablePurgeDelayMillis;
}

RoutingSettings routingSettings() {
return new RoutingSettings(routingTablePurgeDelayMillis);
}

RetrySettings retrySettings() {
return retrySettings;
/**
* Returns managed transactions maximum retry time.
*
* @return maximum retry time
*/
public long maxTransactionRetryTimeMillis() {
return maxTransactionRetryTimeMillis;
}

public long fetchSize() {
Expand Down Expand Up @@ -265,9 +271,9 @@ public static final class ConfigBuilder {
private String userAgent = format("neo4j-java/%s", driverVersion());
private final SecuritySettings.SecuritySettingsBuilder securitySettingsBuilder =
new SecuritySettings.SecuritySettingsBuilder();
private long routingTablePurgeDelayMillis = RoutingSettings.DEFAULT.routingTablePurgeDelayMs();
private long routingTablePurgeDelayMillis = RoutingSettings.STALE_ROUTING_TABLE_PURGE_DELAY_MS;
private int connectionTimeoutMillis = (int) TimeUnit.SECONDS.toMillis(30);
private RetrySettings retrySettings = RetrySettings.DEFAULT;
private long maxTransactionRetryTimeMillis = ExponentialBackoffRetryLogic.DEFAULT_MAX_RETRY_TIME_MS;
private ServerAddressResolver resolver;
private MetricsAdapter metricsAdapter = MetricsAdapter.DEV_NULL;
private long fetchSize = FetchSizeUtil.DEFAULT_FETCH_SIZE;
Expand Down Expand Up @@ -331,7 +337,7 @@ public ConfigBuilder withLeakedSessionsLogging() {
* validity and negative values mean connections will never be tested.
*
* @param value the minimum idle time
* @param unit the unit in which the duration is given
* @param unit the unit in which the duration is given
* @return this builder
*/
public ConfigBuilder withConnectionLivenessCheckTimeout(long value, TimeUnit unit) {
Expand All @@ -356,7 +362,7 @@ public ConfigBuilder withConnectionLivenessCheckTimeout(long value, TimeUnit uni
* checked.
*
* @param value the maximum connection lifetime
* @param unit the unit in which the duration is given
* @param unit the unit in which the duration is given
* @return this builder
*/
public ConfigBuilder withMaxConnectionLifetime(long value, TimeUnit unit) {
Expand Down Expand Up @@ -402,7 +408,7 @@ public ConfigBuilder withMaxConnectionPoolSize(int value) {
* of {@code 0} is allowed and results in no timeout and immediate failure when connection is unavailable.
*
* @param value the acquisition timeout
* @param unit the unit in which the duration is given
* @param unit the unit in which the duration is given
* @return this builder
* @see #withMaxConnectionPoolSize(int)
*/
Expand All @@ -418,6 +424,7 @@ public ConfigBuilder withConnectionAcquisitionTimeout(long value, TimeUnit unit)

/**
* Set to use encrypted traffic.
*
* @return this builder
*/
public ConfigBuilder withEncryption() {
Expand All @@ -427,6 +434,7 @@ public ConfigBuilder withEncryption() {

/**
* Set to use unencrypted traffic.
*
* @return this builder
*/
public ConfigBuilder withoutEncryption() {
Expand Down Expand Up @@ -461,13 +469,12 @@ public ConfigBuilder withTrustStrategy(TrustStrategy trustStrategy) {
* The routing table of a database get refreshed if the database is used frequently.
* If the database is not used for a long time,
* the driver use the timeout specified here to purge the stale routing table.
*
* <p>
* After a routing table is removed, next time when using the database of the purged routing table,
* the driver will fall back to use seed URI for a new routing table.
* @param delay
* the amount of time to wait before purging routing tables
* @param unit
* the unit in which the duration is given
*
* @param delay the amount of time to wait before purging routing tables
* @param unit the unit in which the duration is given
* @return this builder
*/
public ConfigBuilder withRoutingTablePurgeDelay(long delay, TimeUnit unit) {
Expand All @@ -483,15 +490,16 @@ public ConfigBuilder withRoutingTablePurgeDelay(long delay, TimeUnit unit) {
/**
* Specify how many records to fetch in each batch.
* This config is only valid when the driver is used with servers that support Bolt V4 (Server version 4.0 and later).
*
* <p>
* Bolt V4 enables pulling records in batches to allow client to take control of data population and apply back pressure to server.
* This config specifies the default fetch size for all query runs using {@link Session} and {@link org.neo4j.driver.async.AsyncSession}.
* By default, the value is set to {@code 1000}.
* Use {@code -1} to disables back pressure and config client to pull all records at once after each run.
*
* <p>
* This config only applies to run result obtained via {@link Session} and {@link org.neo4j.driver.async.AsyncSession}.
* As with {@link org.neo4j.driver.reactive.RxSession}, the batch size is provided via
* {@link org.reactivestreams.Subscription#request(long)} instead.
*
* @param size the default record fetch size when pulling records in batches using Bolt V4.
* @return this builder
*/
Expand All @@ -512,10 +520,10 @@ public ConfigBuilder withFetchSize(long size) {
* The default value of this parameter is {@code 30 SECONDS}.
*
* @param value the timeout duration
* @param unit the unit in which duration is given
* @param unit the unit in which duration is given
* @return this builder
* @throws IllegalArgumentException when given value is negative or does not fit in {@code int} when
* converted to milliseconds.
* converted to milliseconds.
*/
public ConfigBuilder withConnectionTimeout(long value, TimeUnit unit) {
long connectionTimeoutMillis = unit.toMillis(value);
Expand All @@ -534,16 +542,14 @@ public ConfigBuilder withConnectionTimeout(long value, TimeUnit unit) {
}

/**
* Specify the maximum time transactions are allowed to retry via
* {@link Session#readTransaction(TransactionWork)} and {@link Session#writeTransaction(TransactionWork)}
* methods. These methods will retry the given unit of work on {@link org.neo4j.driver.exceptions.ServiceUnavailableException},
* {@link org.neo4j.driver.exceptions.SessionExpiredException} and {@link org.neo4j.driver.exceptions.TransientException} with
* exponential backoff using initial delay of 1 second.
* Specify the maximum time managed transactions are allowed to retry.
* <p>
* Managed transactions are available via methods like {@link Session#executeRead(TransactionCallback)}, {@link Session#executeWrite(TransactionCallback, TransactionConfig)} and some other variations available under similar naming.
* <p>
* Default value is 30 seconds.
*
* @param value the timeout duration
* @param unit the unit in which duration is given
* @param unit the unit in which duration is given
* @return this builder
* @throws IllegalArgumentException when given value is negative
*/
Expand All @@ -553,7 +559,7 @@ public ConfigBuilder withMaxTransactionRetryTime(long value, TimeUnit unit) {
throw new IllegalArgumentException(
String.format("The max retry time may not be smaller than 0, but was %d %s.", value, unit));
}
this.retrySettings = new RetrySettings(maxRetryTimeMs);
this.maxTransactionRetryTimeMillis = maxRetryTimeMs;
return this;
}

Expand Down Expand Up @@ -586,6 +592,7 @@ public ConfigBuilder withDriverMetrics() {

/**
* Disable driver metrics. When disabled, driver metrics cannot be accessed via {@link Driver#metrics()}.
*
* @return this builder.
*/
public ConfigBuilder withoutDriverMetrics() {
Expand Down Expand Up @@ -619,6 +626,7 @@ public ConfigBuilder withMetricsAdapter(MetricsAdapter metricsAdapter) {
/**
* Configure the event loop thread count. This specifies how many threads the driver can use to handle network I/O events
* and user's events in driver's I/O threads. By default, 2 * NumberOfProcessors amount of threads will be used instead.
*
* @param size the thread count.
* @return this builder.
* @throws IllegalArgumentException if the value of the size is set to a number that is less than 1.
Expand All @@ -634,6 +642,7 @@ public ConfigBuilder withEventLoopThreads(int size) {

/**
* Configure the user_agent field sent to the server to identify the connected client.
*
* @param userAgent the string to configure user_agent.
* @return this builder.
*/
Expand Down Expand Up @@ -802,6 +811,7 @@ public static TrustStrategy trustAllCertificates() {

/**
* The revocation strategy used for verifying certificates.
*
* @return this {@link TrustStrategy}'s revocation strategy
*/
public RevocationCheckingStrategy revocationCheckingStrategy() {
Expand All @@ -811,6 +821,7 @@ public RevocationCheckingStrategy revocationCheckingStrategy() {
/**
* Configures the {@link TrustStrategy} to not carry out OCSP revocation checks on certificates. This is the
* option that is configured by default.
*
* @return the current trust strategy
*/
public TrustStrategy withoutCertificateRevocationChecks() {
Expand All @@ -823,6 +834,7 @@ public TrustStrategy withoutCertificateRevocationChecks() {
* stapled to the certificate. If no stapled response is found, then certificate verification continues
* (and does not fail verification). This setting also requires the server to be configured to enable
* OCSP stapling.
*
* @return the current trust strategy
*/
public TrustStrategy withVerifyIfPresentRevocationChecks() {
Expand All @@ -834,9 +846,10 @@ public TrustStrategy withVerifyIfPresentRevocationChecks() {
* Configures the {@link TrustStrategy} to carry out strict OCSP revocation checks for revocation status that
* are stapled to the certificate. If no stapled response is found, then the driver will fail certificate verification
* and not connect to the server. This setting also requires the server to be configured to enable OCSP stapling.
*
* <p>
* Note: enabling this setting will prevent the driver connecting to the server when the server is unable to reach
* the certificate's configured OCSP responder URL.
*
* @return the current trust strategy
*/
public TrustStrategy withStrictRevocationChecks() {
Expand Down
10 changes: 1 addition & 9 deletions driver/src/main/java/org/neo4j/driver/GraphDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@

import java.net.URI;
import org.neo4j.driver.internal.DriverFactory;
import org.neo4j.driver.internal.SecuritySettings;
import org.neo4j.driver.internal.cluster.RoutingSettings;
import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;

/**
* Creates {@link Driver drivers}, optionally letting you {@link #driver(URI, Config)} to configure them.
Expand Down Expand Up @@ -123,11 +119,7 @@ public static Driver driver(URI uri, AuthToken authToken, Config config) {

static Driver driver(URI uri, AuthToken authToken, Config config, DriverFactory driverFactory) {
config = getOrDefault(config);
RoutingSettings routingSettings = config.routingSettings();
RetrySettings retrySettings = config.retrySettings();
SecuritySettings securitySettings = config.securitySettings();
SecurityPlan securityPlan = securitySettings.createSecurityPlan(uri.getScheme());
return driverFactory.newInstance(uri, authToken, routingSettings, retrySettings, config, securityPlan);
return driverFactory.newInstance(uri, authToken, config);
}

private static Config getOrDefault(Config config) {
Expand Down
36 changes: 18 additions & 18 deletions driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
import org.neo4j.driver.internal.metrics.MicrometerMetricsProvider;
import org.neo4j.driver.internal.retry.ExponentialBackoffRetryLogic;
import org.neo4j.driver.internal.retry.RetryLogic;
import org.neo4j.driver.internal.retry.RetrySettings;
import org.neo4j.driver.internal.security.SecurityPlan;
import org.neo4j.driver.internal.security.SecurityPlans;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.internal.spi.ConnectionProvider;
import org.neo4j.driver.internal.util.Clock;
Expand All @@ -67,25 +67,18 @@ public class DriverFactory {
public static final String NO_ROUTING_CONTEXT_ERROR_MESSAGE =
"Routing parameters are not supported with scheme 'bolt'. Given URI: ";

public final Driver newInstance(
URI uri,
AuthToken authToken,
RoutingSettings routingSettings,
RetrySettings retrySettings,
Config config,
SecurityPlan securityPlan) {
return newInstance(uri, authToken, routingSettings, retrySettings, config, null, securityPlan, null);
public final Driver newInstance(URI uri, AuthToken authToken, Config config) {
return newInstance(uri, authToken, config, null, null, null);
}

public final Driver newInstance(
URI uri,
AuthToken authToken,
RoutingSettings routingSettings,
RetrySettings retrySettings,
Config config,
EventLoopGroup eventLoopGroup,
SecurityPlan securityPlan,
EventLoopGroup eventLoopGroup,
Supplier<Rediscovery> rediscoverySupplier) {

Bootstrap bootstrap;
boolean ownsEventLoopGroup;
if (eventLoopGroup == null) {
Expand All @@ -96,14 +89,21 @@ public final Driver newInstance(
ownsEventLoopGroup = false;
}

if (securityPlan == null) {
var settings = new SecuritySettings(config.encrypted(), config.trustStrategy());
securityPlan = SecurityPlans.createSecurityPlan(settings, uri.getScheme());
}

authToken = authToken == null ? AuthTokens.none() : authToken;

BoltServerAddress address = new BoltServerAddress(uri);
RoutingSettings newRoutingSettings = routingSettings.withRoutingContext(new RoutingContext(uri));
RoutingSettings routingSettings =
new RoutingSettings(config.routingTablePurgeDelayMillis(), new RoutingContext(uri));

InternalLoggerFactory.setDefaultFactory(new NettyLogging(config.logging()));
EventExecutorGroup eventExecutorGroup = bootstrap.config().group();
RetryLogic retryLogic = createRetryLogic(retrySettings, eventExecutorGroup, config.logging());
RetryLogic retryLogic =
createRetryLogic(config.maxTransactionRetryTimeMillis(), eventExecutorGroup, config.logging());

MetricsProvider metricsProvider = getOrCreateMetricsProvider(config, createClock());
ConnectionPool connectionPool = createConnectionPool(
Expand All @@ -113,15 +113,15 @@ public final Driver newInstance(
metricsProvider,
config,
ownsEventLoopGroup,
newRoutingSettings.routingContext());
routingSettings.routingContext());

return createDriver(
uri,
securityPlan,
address,
connectionPool,
eventExecutorGroup,
newRoutingSettings,
routingSettings,
retryLogic,
metricsProvider,
rediscoverySupplier,
Expand Down Expand Up @@ -354,8 +354,8 @@ protected SessionFactory createSessionFactory(
* <b>This method is protected only for testing</b>
*/
protected RetryLogic createRetryLogic(
RetrySettings settings, EventExecutorGroup eventExecutorGroup, Logging logging) {
return new ExponentialBackoffRetryLogic(settings, eventExecutorGroup, createClock(), logging);
long maxTransactionRetryTime, EventExecutorGroup eventExecutorGroup, Logging logging) {
return new ExponentialBackoffRetryLogic(maxTransactionRetryTime, eventExecutorGroup, createClock(), logging);
}

/**
Expand Down
Loading

0 comments on commit a0f5b07

Please sign in to comment.