Skip to content

Commit 5708274

Browse files
authored
Merge pull request #372 from neo4j/1.3-first-available-address
Construct routing driver from first available address
2 parents 1886bfa + 2dab779 commit 5708274

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@
4747

4848
import static java.lang.String.format;
4949
import static org.neo4j.driver.internal.security.SecurityPlan.insecure;
50-
import static org.neo4j.driver.v1.Config.EncryptionLevel.REQUIRED;
5150

5251
public class DriverFactory
5352
{
53+
public static final String BOLT_URI_SCHEME = "bolt";
54+
public static final String BOLT_ROUTING_URI_SCHEME = "bolt+routing";
55+
5456
public final Driver newInstance( URI uri, AuthToken authToken, RoutingSettings routingSettings,
5557
RetrySettings retrySettings, Config config )
5658
{
@@ -86,10 +88,10 @@ private Driver createDriver( URI uri, BoltServerAddress address, ConnectionPool
8688
String scheme = uri.getScheme().toLowerCase();
8789
switch ( scheme )
8890
{
89-
case "bolt":
91+
case BOLT_URI_SCHEME:
9092
assertNoRoutingContext( uri, routingSettings );
9193
return createDirectDriver( address, connectionPool, config, securityPlan, retryLogic );
92-
case "bolt+routing":
94+
case BOLT_ROUTING_URI_SCHEME:
9395
return createRoutingDriver( address, connectionPool, config, routingSettings, securityPlan, retryLogic );
9496
default:
9597
throw new ClientException( format( "Unsupported URI scheme: %s", scheme ) );

driver/src/main/java/org/neo4j/driver/v1/GraphDatabase.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import org.neo4j.driver.internal.DriverFactory;
2424
import org.neo4j.driver.internal.cluster.RoutingSettings;
2525
import org.neo4j.driver.internal.retry.RetrySettings;
26+
import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
27+
28+
import static org.neo4j.driver.internal.DriverFactory.BOLT_ROUTING_URI_SCHEME;
2629

2730
/**
2831
* Creates {@link Driver drivers}, optionally letting you {@link #driver(URI, Config)} to configure them.
@@ -131,4 +134,46 @@ public static Driver driver( URI uri, AuthToken authToken, Config config )
131134

132135
return new DriverFactory().newInstance( uri, authToken, routingSettings, retrySettings, config );
133136
}
137+
138+
/**
139+
* Try to create a bolt+routing driver from the <b>first</b> available address.
140+
* This is wrapper for the {@link #driver} method that finds the <b>first</b>
141+
* server to respond positively.
142+
*
143+
* @param routingUris an {@link Iterable} of server {@link URI}s for Neo4j instances. All given URIs should
144+
* have 'bolt+routing' scheme.
145+
* @param authToken authentication to use, see {@link AuthTokens}
146+
* @param config user defined configuration
147+
* @return a new driver instance
148+
*/
149+
public static Driver routingDriver( Iterable<URI> routingUris, AuthToken authToken, Config config )
150+
{
151+
assertRoutingUris( routingUris );
152+
153+
for ( URI uri : routingUris )
154+
{
155+
try
156+
{
157+
return driver( uri, authToken, config );
158+
}
159+
catch ( ServiceUnavailableException e )
160+
{
161+
// try the next one
162+
}
163+
}
164+
165+
throw new ServiceUnavailableException( "Failed to discover an available server" );
166+
}
167+
168+
private static void assertRoutingUris( Iterable<URI> uris )
169+
{
170+
for ( URI uri : uris )
171+
{
172+
if ( !BOLT_ROUTING_URI_SCHEME.equals( uri.getScheme() ) )
173+
{
174+
throw new IllegalArgumentException(
175+
"Illegal URI scheme, expected '" + BOLT_ROUTING_URI_SCHEME + "' in '" + uri + "'" );
176+
}
177+
}
178+
}
134179
}

driver/src/test/java/org/neo4j/driver/v1/integration/CausalClusteringIT.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.junit.Test;
2323

2424
import java.net.URI;
25+
import java.util.ArrayList;
2526
import java.util.List;
2627
import java.util.concurrent.Callable;
2728
import java.util.concurrent.CountDownLatch;
@@ -66,6 +67,7 @@
6667
import static org.junit.Assert.assertThat;
6768
import static org.junit.Assert.assertTrue;
6869
import static org.junit.Assert.fail;
70+
import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
6971
import static org.neo4j.driver.v1.Values.parameters;
7072

7173
public class CausalClusteringIT
@@ -85,6 +87,16 @@ public void shouldExecuteReadAndWritesWhenDriverSuppliedWithAddressOfLeader() th
8587
assertEquals( 1, count );
8688
}
8789

90+
@Test
91+
public void shouldExecuteReadAndWritesWhenRouterIsDiscovered() throws Exception
92+
{
93+
Cluster cluster = clusterRule.getCluster();
94+
95+
int count = executeWriteAndReadThroughBoltOnFirstAvailableAddress( cluster.anyReadReplica(), cluster.leader() );
96+
97+
assertEquals( 1, count );
98+
}
99+
88100
@Test
89101
public void shouldExecuteReadAndWritesWhenDriverSuppliedWithAddressOfFollower() throws Exception
90102
{
@@ -446,6 +458,19 @@ private int executeWriteAndReadThroughBolt( ClusterMember member ) throws Timeou
446458
}
447459
}
448460

461+
private int executeWriteAndReadThroughBoltOnFirstAvailableAddress( ClusterMember... members ) throws TimeoutException, InterruptedException
462+
{
463+
List<URI> addresses = new ArrayList<>( members.length );
464+
for ( ClusterMember member : members )
465+
{
466+
addresses.add( member.getRoutingUri() );
467+
}
468+
try ( Driver driver = discoverDriver( addresses ) )
469+
{
470+
return inExpirableSession( driver, createWritableSession( null ), executeWriteAndRead() );
471+
}
472+
}
473+
449474
private Function<Driver,Session> createSession()
450475
{
451476
return new Function<Driver,Session>()
@@ -592,6 +617,15 @@ public Logger getLog( String name )
592617
return GraphDatabase.driver( boltUri, clusterRule.getDefaultAuthToken(), config );
593618
}
594619

620+
private Driver discoverDriver( List<URI> routingUris )
621+
{
622+
Config config = Config.build()
623+
.withLogging( DEV_NULL_LOGGING )
624+
.toConfig();
625+
626+
return GraphDatabase.routingDriver( routingUris, clusterRule.getDefaultAuthToken(), config );
627+
}
628+
595629
private static void createNodesInDifferentThreads( int count, final Driver driver ) throws Exception
596630
{
597631
final CountDownLatch beforeRunLatch = new CountDownLatch( count );

driver/src/test/java/org/neo4j/driver/v1/util/cc/LocalOrRemoteClusterRule.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.neo4j.driver.v1.AuthToken;
2626
import org.neo4j.driver.v1.AuthTokens;
2727

28+
import static org.neo4j.driver.internal.DriverFactory.BOLT_ROUTING_URI_SCHEME;
29+
2830
public class LocalOrRemoteClusterRule extends ExternalResource
2931
{
3032
private static final String CLUSTER_URI_SYSTEM_PROPERTY_NAME = "externalClusterUri";
@@ -88,7 +90,7 @@ private static void assertValidSystemPropertiesDefined()
8890
"Both cluster uri and 'neo4j' user password system properties should be set. " +
8991
"Uri: '" + uri + "', Password: '" + password + "'" );
9092
}
91-
if ( uri != null && !"bolt+routing".equals( uri.getScheme() ) )
93+
if ( uri != null && !BOLT_ROUTING_URI_SCHEME.equals( uri.getScheme() ) )
9294
{
9395
throw new IllegalStateException( "CLuster uri should have bolt+routing scheme: '" + uri + "'" );
9496
}

0 commit comments

Comments
 (0)