Skip to content

Commit e7b8c21

Browse files
authored
Make AddressSet retain resolved addresses (#1034)
Routing table address set update may override resolved router address. This leads to routing connection pool closures. This update aims to optimise this.
1 parent 9034eb9 commit e7b8c21

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,23 @@ public int size()
4040
return addresses.length;
4141
}
4242

43+
/**
44+
* Updates addresses using the provided set.
45+
* <p>
46+
* It aims to retain existing addresses by checking if they are present in the new set. To benefit from this, the provided set MUST contain specifically
47+
* {@link BoltServerAddress} instances with equal host and connection host values.
48+
*
49+
* @param newAddresses the new address set.
50+
*/
4351
public synchronized void retainAllAndAdd( Set<BoltServerAddress> newAddresses )
4452
{
4553
BoltServerAddress[] addressesArr = new BoltServerAddress[newAddresses.size()];
4654
int insertionIdx = 0;
4755
for ( BoltServerAddress address : addresses )
4856
{
49-
if ( newAddresses.remove( address ) )
57+
BoltServerAddress lookupAddress =
58+
BoltServerAddress.class.equals( address.getClass() ) ? address : new BoltServerAddress( address.host(), address.port() );
59+
if ( newAddresses.remove( lookupAddress ) )
5060
{
5161
addressesArr[insertionIdx] = address;
5262
insertionIdx++;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ private synchronized void freshClusterCompositionFetched( ClusterCompositionLook
136136
{
137137
try
138138
{
139+
log.debug( "Fetched cluster composition for database '%s'. %s", databaseName.description(), compositionLookupResult.getClusterComposition() );
139140
routingTable.update( compositionLookupResult.getClusterComposition() );
140141
routingTableRegistry.removeAged();
141142

@@ -166,7 +167,8 @@ private synchronized void freshClusterCompositionFetched( ClusterCompositionLook
166167

167168
private synchronized void clusterCompositionLookupFailed( Throwable error )
168169
{
169-
log.error( String.format( "Failed to update routing table for database '%s'. Current routing table: %s.", databaseName.description(), routingTable ), error );
170+
log.error( String.format( "Failed to update routing table for database '%s'. Current routing table: %s.", databaseName.description(), routingTable ),
171+
error );
170172
routingTableRegistry.remove( databaseName );
171173
CompletableFuture<RoutingTable> routingTableFuture = refreshRoutingTableFuture;
172174
refreshRoutingTableFuture = null;

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020

2121
import org.junit.jupiter.api.Test;
2222

23+
import java.net.InetAddress;
24+
import java.util.Arrays;
25+
import java.util.HashSet;
2326
import java.util.LinkedHashSet;
2427
import java.util.Set;
2528

2629
import org.neo4j.driver.internal.BoltServerAddress;
30+
import org.neo4j.driver.internal.ResolvedBoltServerAddress;
2731

2832
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2933
import static org.junit.jupiter.api.Assertions.assertEquals;
34+
import static org.junit.jupiter.api.Assertions.assertSame;
3035

3136
class AddressSetTest
3237
{
@@ -142,6 +147,32 @@ void shouldHaveCorrectSize()
142147
assertEquals( 2, addressSet.size() );
143148
}
144149

150+
@Test
151+
void shouldRetainExistingAddresses()
152+
{
153+
AddressSet addressSet = new AddressSet();
154+
BoltServerAddress address0 = new BoltServerAddress( "node0", 7687 );
155+
BoltServerAddress address1 = new ResolvedBoltServerAddress( "node1", 7687, new InetAddress[]{InetAddress.getLoopbackAddress()} );
156+
BoltServerAddress address2 = new BoltServerAddress( "node2", 7687 );
157+
BoltServerAddress address3 = new BoltServerAddress( "node3", 7687 );
158+
BoltServerAddress address4 = new BoltServerAddress( "node4", 7687 );
159+
addressSet.retainAllAndAdd( new HashSet<>( Arrays.asList( address0, address1, address2, address3, address4 ) ) );
160+
161+
BoltServerAddress sameAddress0 = new BoltServerAddress( "node0", 7687 );
162+
BoltServerAddress sameAddress1 = new BoltServerAddress( "node1", 7687 );
163+
BoltServerAddress differentAddress2 = new BoltServerAddress( "different-node2", 7687 );
164+
BoltServerAddress sameAddress3 = new BoltServerAddress( "node3", 7687 );
165+
BoltServerAddress sameAddress4 = new BoltServerAddress( "node4", 7687 );
166+
addressSet.retainAllAndAdd( new HashSet<>( Arrays.asList( sameAddress0, sameAddress1, differentAddress2, sameAddress3, sameAddress4 ) ) );
167+
168+
assertEquals( 5, addressSet.size() );
169+
assertSame( addressSet.toArray()[0], address0 );
170+
assertSame( addressSet.toArray()[1], address1 );
171+
assertSame( addressSet.toArray()[2], address3 );
172+
assertSame( addressSet.toArray()[3], address4 );
173+
assertSame( addressSet.toArray()[4], differentAddress2 );
174+
}
175+
145176
private static Set<BoltServerAddress> addresses( String... strings )
146177
{
147178
Set<BoltServerAddress> set = new LinkedHashSet<>();

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.util.function.Function;
3333
import java.util.stream.Collectors;
3434

35-
import org.neo4j.driver.internal.BoltServerAddress;
3635
import org.neo4j.driver.internal.DatabaseName;
3736
import org.neo4j.driver.internal.DatabaseNameUtil;
3837
import org.neo4j.driver.internal.cluster.AddressSet;
@@ -43,6 +42,11 @@
4342
@Getter
4443
public class GetRoutingTable implements TestkitRequest
4544
{
45+
private static final Function<AddressSet,List<String>> ADDRESSES_TO_STRINGS =
46+
( addresses ) -> Arrays.stream( addresses.toArray() )
47+
.map( address -> String.format( "%s:%d", address.host(), address.port() ) )
48+
.collect( Collectors.toList() );
49+
4650
private GetRoutingTableBody data;
4751

4852
@Override
@@ -61,17 +65,15 @@ public TestkitResponse process( TestkitState testkitState )
6165
String.format( "There is no routing table handler for the '%s' database.", databaseName.databaseName().orElse( "null" ) ) ) );
6266

6367
org.neo4j.driver.internal.cluster.RoutingTable routingTable = routingTableHandler.routingTable();
64-
Function<AddressSet,List<String>> addressesToStrings = ( addresses ) -> Arrays.stream( addresses.toArray() )
65-
.map( BoltServerAddress::toString ).collect( Collectors.toList() );
6668

6769
return RoutingTable
6870
.builder()
6971
.data( RoutingTable.RoutingTableBody
7072
.builder()
7173
.database( databaseName.databaseName().orElse( null ) )
72-
.routers( addressesToStrings.apply( routingTable.routers() ) )
73-
.readers( addressesToStrings.apply( routingTable.readers() ) )
74-
.writers( addressesToStrings.apply( routingTable.writers() ) )
74+
.routers( ADDRESSES_TO_STRINGS.apply( routingTable.routers() ) )
75+
.readers( ADDRESSES_TO_STRINGS.apply( routingTable.readers() ) )
76+
.writers( ADDRESSES_TO_STRINGS.apply( routingTable.writers() ) )
7577
.build()
7678
).build();
7779
}

0 commit comments

Comments
 (0)