Skip to content

Commit aa9e9cc

Browse files
committed
Treat one router as valid in routing table
Previously driver considered routing table with single router to be stale and had to perform rediscovery before read/write transaction. Requirement to have more than 1 router is quite strict and can easily be violated by partially unavailable clusters. Additional rediscoveries in such cases add more load on the available core server. This commit makes driver tread routing table with single router as not stale, given that other non-staleness requirements are satisfied as well.
1 parent c163634 commit aa9e9cc

File tree

4 files changed

+56
-17
lines changed

4 files changed

+56
-17
lines changed

driver/src/main/java/org/neo4j/driver/internal/cluster/ClusterRoutingTable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private ClusterRoutingTable( Clock clock )
6060
public boolean isStaleFor( AccessMode mode )
6161
{
6262
return expirationTimeout < clock.millis() ||
63-
routers.size() <= MIN_ROUTERS ||
63+
routers.size() < MIN_ROUTERS ||
6464
mode == AccessMode.READ && readers.size() == 0 ||
6565
mode == AccessMode.WRITE && writers.size() == 0;
6666
}

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

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -963,22 +963,7 @@ public void shouldAcceptRoutingTableWithoutWritersAndThenRediscover() throws Exc
963963
// start another router which knows about writes, use same address as the initial router
964964
router2 = StubServer.start( "acquire_endpoints.script", 9010 );
965965

966-
List<String> names = session.readTransaction( new TransactionWork<List<String>>()
967-
{
968-
@Override
969-
public List<String> execute( Transaction tx )
970-
{
971-
List<Record> records = tx.run( "MATCH (n) RETURN n.name" ).list();
972-
List<String> names = new ArrayList<>( records.size() );
973-
for ( Record record : records )
974-
{
975-
names.add( record.get( 0 ).asString() );
976-
}
977-
return names;
978-
}
979-
} );
980-
981-
assertEquals( asList( "Bob", "Alice", "Tina" ), names );
966+
assertEquals( asList( "Bob", "Alice", "Tina" ), readStrings( "MATCH (n) RETURN n.name", session ) );
982967

983968
StatementResult createResult = session.run( "CREATE (n {name:'Bob'})" );
984969
assertFalse( createResult.hasNext() );
@@ -993,6 +978,35 @@ public List<String> execute( Transaction tx )
993978
}
994979
}
995980

981+
@Test
982+
public void shouldTreatRoutingTableWithSingleRouterAsValid() throws Exception
983+
{
984+
StubServer router = StubServer.start( "discover_one_router.script", 9010 );
985+
StubServer reader1 = StubServer.start( "read_server.script", 9003 );
986+
StubServer reader2 = StubServer.start( "read_server.script", 9004 );
987+
988+
try ( Driver driver = GraphDatabase.driver( "bolt+routing://127.0.0.1:9010", config );
989+
Session session = driver.session( AccessMode.READ ) )
990+
{
991+
// returned routing table contains only one router, this should be fine and we should be able to
992+
// read multiple times without additional rediscovery
993+
994+
StatementResult readResult1 = session.run( "MATCH (n) RETURN n.name" );
995+
assertEquals( "127.0.0.1:9003", readResult1.summary().server().address() );
996+
assertEquals( 3, readResult1.list().size() );
997+
998+
StatementResult readResult2 = session.run( "MATCH (n) RETURN n.name" );
999+
assertEquals( "127.0.0.1:9004", readResult2.summary().server().address() );
1000+
assertEquals( 3, readResult2.list().size() );
1001+
}
1002+
finally
1003+
{
1004+
assertEquals( 0, router.exitStatus() );
1005+
assertEquals( 0, reader1.exitStatus() );
1006+
assertEquals( 0, reader2.exitStatus() );
1007+
}
1008+
}
1009+
9961010
private static Driver newDriverWithSleeplessClock( String uriString )
9971011
{
9981012
DriverFactory driverFactory = new DriverFactoryWithClock( new SleeplessClock() );

driver/src/test/java/org/neo4j/driver/internal/cluster/ClusterRoutingTableTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.neo4j.driver.internal.util.FakeClock;
2727

2828
import static java.util.Arrays.asList;
29+
import static java.util.Collections.singletonList;
2930
import static org.junit.Assert.assertEquals;
3031
import static org.junit.Assert.assertFalse;
3132
import static org.junit.Assert.assertTrue;
@@ -181,4 +182,19 @@ public void shouldPreserveOrderingOfReaders()
181182
assertEquals( D, routingTable.readers().next() );
182183
assertEquals( B, routingTable.readers().next() );
183184
}
185+
186+
@Test
187+
public void shouldTreatOneRouterAsValid()
188+
{
189+
ClusterRoutingTable routingTable = new ClusterRoutingTable( new FakeClock() );
190+
191+
List<BoltServerAddress> routers = singletonList( A );
192+
List<BoltServerAddress> writers = asList( B, C );
193+
List<BoltServerAddress> readers = asList( D, E );
194+
195+
routingTable.update( createClusterComposition( routers, writers, readers ) );
196+
197+
assertFalse( routingTable.isStaleFor( READ ) );
198+
assertFalse( routingTable.isStaleFor( WRITE ) );
199+
}
184200
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
!: AUTO INIT
2+
!: AUTO RESET
3+
!: AUTO PULL_ALL
4+
5+
C: RUN "CALL dbms.cluster.routing.getServers" {}
6+
PULL_ALL
7+
S: SUCCESS {"fields": ["ttl", "servers"]}
8+
RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9003","127.0.0.1:9004"], "role": "READ"},{"addresses": ["127.0.0.1:9005"], "role": "ROUTE"}]]
9+
SUCCESS {}

0 commit comments

Comments
 (0)