Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 2 access options to Config and refactor DriverFactory #1356

Merged
merged 1 commit into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much nicer :)

}

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