Skip to content

Commit a81d882

Browse files
authored
Merge pull request #241 from pontusmelke/1.1-remove-address-on-connection-failure
Remove server when failing on session acquisition
2 parents 9fc758f + b4885f6 commit a81d882

File tree

4 files changed

+78
-11
lines changed

4 files changed

+78
-11
lines changed

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

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public int compare( BoltServerAddress o1, BoltServerAddress o2 )
6464
}
6565
};
6666
private static final int MIN_SERVERS = 1;
67+
private static final int CONNECTION_RETRIES = 3;
6768
private final ConnectionPool connections;
6869
private final Function<Connection,Session> sessionProvider;
6970
private final Clock clock;
@@ -108,7 +109,6 @@ private Set<BoltServerAddress> forgetAllServers()
108109
seen.addAll( routingServers );
109110
seen.addAll( readServers );
110111
seen.addAll( writeServers );
111-
routingServers.clear();
112112
readServers.clear();
113113
writeServers.clear();
114114
return seen;
@@ -136,11 +136,11 @@ private void getServers()
136136
{
137137
boolean success = false;
138138

139-
ConcurrentRoundRobinSet<BoltServerAddress> routers = new ConcurrentRoundRobinSet<>( routingServers );
139+
final Set<BoltServerAddress> newRouters = new HashSet<>( );
140140
final Set<BoltServerAddress> seen = forgetAllServers();
141-
while ( !routers.isEmpty() && !success )
141+
while ( !routingServers.isEmpty() && !success )
142142
{
143-
address = routers.hop();
143+
address = routingServers.hop();
144144
success = call( address, GET_SERVERS, new Consumer<Record>()
145145
{
146146
@Override
@@ -160,12 +160,19 @@ public void accept( Record record )
160160
writeServers.addAll( server.addresses() );
161161
break;
162162
case "ROUTE":
163-
routingServers.addAll( server.addresses() );
163+
newRouters.addAll( server.addresses() );
164164
break;
165165
}
166166
}
167167
}
168168
} );
169+
//We got trough but server gave us an empty list of routers
170+
if (success && newRouters.isEmpty()) {
171+
success = false;
172+
} else if (success) {
173+
routingServers.clear();
174+
routingServers.addAll( newRouters );
175+
}
169176
}
170177
if ( !success )
171178
{
@@ -247,7 +254,7 @@ private boolean call( BoltServerAddress address, String procedureName, Consumer<
247254
recorder.accept( records.next() );
248255
}
249256
}
250-
catch ( ConnectionFailureException e )
257+
catch ( Throwable e )
251258
{
252259
forget( address );
253260
return false;
@@ -303,18 +310,36 @@ public void onWriteFailure( BoltServerAddress address )
303310

304311
private Connection acquireConnection( AccessMode role )
305312
{
306-
//Potentially rediscover servers if we are not happy with our current knowledge
307-
checkServers();
308-
313+
ConcurrentRoundRobinSet<BoltServerAddress> servers;
309314
switch ( role )
310315
{
311316
case READ:
312-
return connections.acquire( readServers.hop() );
317+
servers = readServers;
318+
break;
313319
case WRITE:
314-
return connections.acquire( writeServers.hop() );
320+
servers = writeServers;
321+
break;
315322
default:
316323
throw new ClientException( role + " is not supported for creating new sessions" );
317324
}
325+
326+
//Potentially rediscover servers if we are not happy with our current knowledge
327+
checkServers();
328+
int numberOfServers = servers.size();
329+
for ( int i = 0; i < numberOfServers; i++ )
330+
{
331+
BoltServerAddress address = servers.hop();
332+
try
333+
{
334+
return connections.acquire( address );
335+
}
336+
catch ( ConnectionFailureException e )
337+
{
338+
forget( address );
339+
}
340+
}
341+
342+
throw new ConnectionFailureException( "Failed to connect to any servers" );
318343
}
319344

320345
@Override

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public void close()
7474
}
7575
}
7676

77+
public BoltServerAddress address()
78+
{
79+
return connection.address();
80+
}
81+
7782
static Neo4jException filterFailureToWrite( ClientException e, AccessMode mode, RoutingErrorHandler onError,
7883
BoltServerAddress address )
7984
{

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,8 @@ public ResultSummary consume()
192192
}
193193
}
194194

195+
public BoltServerAddress address()
196+
{
197+
return address;
198+
}
195199
}

driver/src/test/java/org/neo4j/driver/internal/RoutingDriverStubTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@
4141
import org.neo4j.driver.v1.GraphDatabase;
4242
import org.neo4j.driver.v1.Record;
4343
import org.neo4j.driver.v1.Session;
44+
import org.neo4j.driver.v1.exceptions.ConnectionFailureException;
4445
import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
4546
import org.neo4j.driver.v1.exceptions.SessionExpiredException;
4647
import org.neo4j.driver.v1.util.Function;
4748
import org.neo4j.driver.v1.util.StubServer;
4849

4950
import static org.hamcrest.Matchers.contains;
5051
import static org.hamcrest.Matchers.containsInAnyOrder;
52+
import static org.hamcrest.Matchers.empty;
5153
import static org.hamcrest.Matchers.hasItem;
5254
import static org.hamcrest.Matchers.hasSize;
5355
import static org.hamcrest.core.IsEqual.equalTo;
@@ -329,6 +331,37 @@ public void shouldForgetEndpointsOnFailure() throws IOException, InterruptedExce
329331
assertThat( server.exitStatus(), equalTo( 0 ) );
330332
}
331333

334+
@Test
335+
public void shouldForgetEndpointsOnFailedSessionAcquisition() throws IOException, InterruptedException, StubServer.ForceKilled
336+
{
337+
// Given
338+
StubServer server = StubServer.start( resource( "acquire_endpoints.script" ), 9001 );
339+
340+
//no read servers
341+
342+
URI uri = URI.create( "bolt+routing://127.0.0.1:9001" );
343+
RoutingDriver driver = (RoutingDriver) GraphDatabase.driver( uri, config );
344+
try
345+
{
346+
driver.session( AccessMode.READ );
347+
fail();
348+
}
349+
catch ( ConnectionFailureException e )
350+
{
351+
//ignore
352+
}
353+
354+
assertThat( driver.readServers(), empty() );
355+
assertThat( driver.writeServers(), hasSize( 2 ) );
356+
assertFalse( driver.connectionPool().hasAddress( address( 9005 ) ) );
357+
assertFalse( driver.connectionPool().hasAddress( address( 9006 ) ) );
358+
driver.close();
359+
360+
// Finally
361+
assertThat( server.exitStatus(), equalTo( 0 ) );
362+
}
363+
364+
332365
@Test
333366
public void shouldRediscoverIfNecessaryOnSessionAcquisition()
334367
throws IOException, InterruptedException, StubServer.ForceKilled

0 commit comments

Comments
 (0)