diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/AddressSet.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/AddressSet.java
index c4cc3f2b20..a08a914ea9 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/cluster/AddressSet.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/AddressSet.java
@@ -40,13 +40,23 @@ public int size()
return addresses.length;
}
+ /**
+ * Updates addresses using the provided set.
+ *
+ * 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
+ * {@link BoltServerAddress} instances with equal host and connection host values.
+ *
+ * @param newAddresses the new address set.
+ */
public synchronized void retainAllAndAdd( Set newAddresses )
{
BoltServerAddress[] addressesArr = new BoltServerAddress[newAddresses.size()];
int insertionIdx = 0;
for ( BoltServerAddress address : addresses )
{
- if ( newAddresses.remove( address ) )
+ BoltServerAddress lookupAddress =
+ BoltServerAddress.class.equals( address.getClass() ) ? address : new BoltServerAddress( address.host(), address.port() );
+ if ( newAddresses.remove( lookupAddress ) )
{
addressesArr[insertionIdx] = address;
insertionIdx++;
diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java
index 5385a5cdda..99c6dbfdf5 100644
--- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java
+++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RoutingTableHandlerImpl.java
@@ -136,6 +136,7 @@ private synchronized void freshClusterCompositionFetched( ClusterCompositionLook
{
try
{
+ log.debug( "Fetched cluster composition for database '%s'. %s", databaseName.description(), compositionLookupResult.getClusterComposition() );
routingTable.update( compositionLookupResult.getClusterComposition() );
routingTableRegistry.removeAged();
@@ -166,7 +167,8 @@ private synchronized void freshClusterCompositionFetched( ClusterCompositionLook
private synchronized void clusterCompositionLookupFailed( Throwable error )
{
- log.error( String.format( "Failed to update routing table for database '%s'. Current routing table: %s.", databaseName.description(), routingTable ), error );
+ log.error( String.format( "Failed to update routing table for database '%s'. Current routing table: %s.", databaseName.description(), routingTable ),
+ error );
routingTableRegistry.remove( databaseName );
CompletableFuture routingTableFuture = refreshRoutingTableFuture;
refreshRoutingTableFuture = null;
diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/AddressSetTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/AddressSetTest.java
index 57b80fac8a..a91d5676b6 100644
--- a/driver/src/test/java/org/neo4j/driver/internal/cluster/AddressSetTest.java
+++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/AddressSetTest.java
@@ -20,13 +20,18 @@
import org.junit.jupiter.api.Test;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.neo4j.driver.internal.BoltServerAddress;
+import org.neo4j.driver.internal.ResolvedBoltServerAddress;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
class AddressSetTest
{
@@ -142,6 +147,32 @@ void shouldHaveCorrectSize()
assertEquals( 2, addressSet.size() );
}
+ @Test
+ void shouldRetainExistingAddresses()
+ {
+ AddressSet addressSet = new AddressSet();
+ BoltServerAddress address0 = new BoltServerAddress( "node0", 7687 );
+ BoltServerAddress address1 = new ResolvedBoltServerAddress( "node1", 7687, new InetAddress[]{InetAddress.getLoopbackAddress()} );
+ BoltServerAddress address2 = new BoltServerAddress( "node2", 7687 );
+ BoltServerAddress address3 = new BoltServerAddress( "node3", 7687 );
+ BoltServerAddress address4 = new BoltServerAddress( "node4", 7687 );
+ addressSet.retainAllAndAdd( new HashSet<>( Arrays.asList( address0, address1, address2, address3, address4 ) ) );
+
+ BoltServerAddress sameAddress0 = new BoltServerAddress( "node0", 7687 );
+ BoltServerAddress sameAddress1 = new BoltServerAddress( "node1", 7687 );
+ BoltServerAddress differentAddress2 = new BoltServerAddress( "different-node2", 7687 );
+ BoltServerAddress sameAddress3 = new BoltServerAddress( "node3", 7687 );
+ BoltServerAddress sameAddress4 = new BoltServerAddress( "node4", 7687 );
+ addressSet.retainAllAndAdd( new HashSet<>( Arrays.asList( sameAddress0, sameAddress1, differentAddress2, sameAddress3, sameAddress4 ) ) );
+
+ assertEquals( 5, addressSet.size() );
+ assertSame( addressSet.toArray()[0], address0 );
+ assertSame( addressSet.toArray()[1], address1 );
+ assertSame( addressSet.toArray()[2], address3 );
+ assertSame( addressSet.toArray()[3], address4 );
+ assertSame( addressSet.toArray()[4], differentAddress2 );
+ }
+
private static Set addresses( String... strings )
{
Set set = new LinkedHashSet<>();
diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java
index 41d2bf0d66..99bea9d694 100644
--- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java
+++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java
@@ -32,7 +32,6 @@
import java.util.function.Function;
import java.util.stream.Collectors;
-import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.internal.DatabaseName;
import org.neo4j.driver.internal.DatabaseNameUtil;
import org.neo4j.driver.internal.cluster.AddressSet;
@@ -43,6 +42,11 @@
@Getter
public class GetRoutingTable implements TestkitRequest
{
+ private static final Function> ADDRESSES_TO_STRINGS =
+ ( addresses ) -> Arrays.stream( addresses.toArray() )
+ .map( address -> String.format( "%s:%d", address.host(), address.port() ) )
+ .collect( Collectors.toList() );
+
private GetRoutingTableBody data;
@Override
@@ -61,17 +65,15 @@ public TestkitResponse process( TestkitState testkitState )
String.format( "There is no routing table handler for the '%s' database.", databaseName.databaseName().orElse( "null" ) ) ) );
org.neo4j.driver.internal.cluster.RoutingTable routingTable = routingTableHandler.routingTable();
- Function> addressesToStrings = ( addresses ) -> Arrays.stream( addresses.toArray() )
- .map( BoltServerAddress::toString ).collect( Collectors.toList() );
return RoutingTable
.builder()
.data( RoutingTable.RoutingTableBody
.builder()
.database( databaseName.databaseName().orElse( null ) )
- .routers( addressesToStrings.apply( routingTable.routers() ) )
- .readers( addressesToStrings.apply( routingTable.readers() ) )
- .writers( addressesToStrings.apply( routingTable.writers() ) )
+ .routers( ADDRESSES_TO_STRINGS.apply( routingTable.routers() ) )
+ .readers( ADDRESSES_TO_STRINGS.apply( routingTable.readers() ) )
+ .writers( ADDRESSES_TO_STRINGS.apply( routingTable.writers() ) )
.build()
).build();
}